Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Difference between array_filter() and array_map()? [duplicate]

Tags:

I looked into the similar topics in web as well stack overflow, but could get this one into my head clearly. Difference between array_map, array_walk and array_filter

<?php error_reporting(-1);  $arr = array(2.4, 2.6, 3.5);  print_r(array_map(function($a) {     $a > 2.5; },$arr));  print_r(array_filter($arr, function($a){     return $a > 2.5; }));  ?> 

The above code returns me a filtered array whose value is > 2.5. Can i achieve what an array_filter does with an array_map?.

like image 582
John Cooper Avatar asked Oct 31 '13 05:10

John Cooper


People also ask

What exactly is the the difference between array_map Array_walk and Array_filter?

The resulting array of array_map has the same length as that of the largest input array; array_walk does not return an array but at the same time it cannot alter the number of elements of original array; array_filter picks only a subset of the elements of the array according to a filtering function.

What is array_map function in PHP?

The array_map() is an inbuilt function in PHP and it helps to modify all elements one or more arrays according to some user-defined condition in an easy manner. It basically, sends each of the elements of an array to a user-defined function and returns an array with new values as modified by that function.

Does PHP have a map function?

The array_map() function sends each value of an array to a user-made function, and returns an array with new values, given by the user-made function.


2 Answers

All three, array_filter, array_map, and array_walk, use a callback function to loop through an array much in the same way foreach loops loop through an $array using $key => $value pairs.
For the duration of this post, I will be referring to the original array, passed to the above mentioned functions, as $array, the index, of the current item in the loop, as $key, and the value, of the current item in the loop, as $value.

array_filter is likened to MySQL's SELECT query which SELECTs records but doesn't modify them.
array_filter's callback is passed the $value of the current loop item and whatever the callback returns is treated as a boolean.
If true, the item is included in the results.
If false, the item is excluded from the results.
Thus you might do:

<pre><?php $users=array('user1'=>array('logged_in'=>'Y'),'user2'=>array('logged_in'=>'N'),'user3'=>array('logged_in'=>'Y'),'user4'=>array('logged_in'=>'Y'),'user5'=>array('logged_in'=>'N')); function signedIn($value) {     if($value['logged_in']=='Y')return true;     return false; } $signedInUsers=array_filter($users,'signedIn'); print_r($signedInUsers);//Array ( [user1] => Array ( [logged_in] => Y ) [user3] => Array ( [logged_in] => Y ) [user4] => Array ( [logged_in] => Y ) ) ?></pre> 

array_map on the other hand accepts multiple arrays as arguments. If one array is specified, the $value of the current item in the loop is sent to the callback. If two or more arrays are used, all the arrays need to first be passed through array_values as mentioned in the documentation:

If the array argument contains string keys then the returned array will contain string keys if and only if exactly one array is passed. If more than one argument is passed then the returned array always has integer keys

The first array is looped through and its value is passed to the callback as its first parameter, and if a second array is specified it will also be looped through and its value will be sent as the 2nd parameter to the callback and so-on and so-forth for each additional parameter.
If the length of the arrays don't match, the largest array is used, as mentioned in the documentation:

Usually when using two or more arrays, they should be of equal length because the callback function is applied in parallel to the corresponding elements. If the arrays are of unequal length, shorter ones will be extended with empty elements to match the length of the longest.

Each time the callback is called, the return value is collected. The keys are preserved only when working with one array, and array_map returns the resulting array. If working with two or more arrays, the keys are lost and instead a new array populated with the callback results is returned. array_map only sends the callback the $value of the current item not its $key. If you need the key as well, you can pass array_keys($array) as an additional argument then the callback will receive both the $key and $value.
However, when using multiple arrays, the original keys will be lost in much the same manner as array_values discards the keys. If you need the keys to be preserved, you can use array_keys to grab the keys from the original array and array_values to grab the values from the result of array_map, or just use the result of array_map directly since it is already returning the values, then combine the two using array_combine.

Thus you might do:

<pre><?php $array=array('apple'=>'a','orange'=>'o'); function fn($key,$value) {     return $value.' is for '.$key; } $result=array_map('fn',array_keys($array),$array); print_r($result);//Array ( [0] => a is for apple [1] => o is for orange ) print_r(array_combine(array_keys($array),$result));//Array ( [apple] => a is for apple [orange] => o is for orange ) ?></pre> 

array_walk is very similar to foreach($array as $key=>$value) in that the callback is sent both a key and a value. It also accepts an optional argument if you want to pass in a 3rd argument directly to the callback.
array_walk returns a boolean value indicating whether the loop completed successfully.
(I have yet to find a practical use for it)
Note that array_walk doesn't make use of the callback's return. Since array_walk returns a boolean value, in order for array_walk to affect something, you'll need to reference &$value so you have that which to modify or use a global array. Alternatively, if you don't want to pollute the global scope, array_walk's optional 3rd argument can be used to pass in a reference to a variable with which to write to.

Thus you might do:

<pre><?php $readArray=array(1=>'January',2=>'February',3=>'March',4=>'April',5=>'May',6=>'June',7=>'July',8=>'August',9=>'September',10=>'October',11=>'November',12=>'December'); $writeArray=array(); function fn($value,$key,&$writeArray) {   $writeArray[$key]=substr($value,0,3); } array_walk($readArray,'fn',&$writeArray); print_r($writeArray);//Array ( [1] => Jan [2] => Feb [3] => Mar [4] => Apr [5] => May [6] => Jun [7] => Jul [8] => Aug [9] => Sep [10] => Oct [11] => Nov [12] => Dec ) ?></pre> 
like image 131
Ultimater Avatar answered Oct 26 '22 04:10

Ultimater


array_filter returns the elements of the original array for which the function returns true.

array_map returns an array of the results of calling the function on all the elements of the original array.

I can't think of a situation where you could use one instead of the other.

like image 38
Barmar Avatar answered Oct 26 '22 04:10

Barmar