Difference between array_map, array_walk and array_filter
- Changing Values:
array_map
cannot change the values inside input array(s) whilearray_walk
can; in particular,array_map
never changes its arguments.
- Array Keys Access:
array_map
cannot operate with the array keys,array_walk
can.
- Return Value:
array_map
returns a new array,array_walk
only returnstrue
. Hence, if you don't want to create an array as a result of traversing one array, you should usearray_walk
.
- Iterating Multiple Arrays:
array_map
also can receive an arbitrary number of arrays and it can iterate over them in parallel, whilearray_walk
operates only on one.
- Passing Arbitrary Data to Callback:
array_walk
can receive an extra arbitrary parameter to pass to the callback. This mostly irrelevant since PHP 5.3 (when anonymous functions were introduced).
- Length of Returned Array:
- 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. It does preserve the keys.
- The resulting array of
Example:
<pre>
<?php
$origarray1 = array(2.4, 2.6, 3.5);
$origarray2 = array(2.4, 2.6, 3.5);
print_r(array_map('floor', $origarray1)); // $origarray1 stays the same
// changes $origarray2
array_walk($origarray2, function (&$v, $k) { $v = floor($v); });
print_r($origarray2);
// this is a more proper use of array_walk
array_walk($origarray1, function ($v, $k) { echo "$k => $v", "\n"; });
// array_map accepts several arrays
print_r(
array_map(function ($a, $b) { return $a * $b; }, $origarray1, $origarray2)
);
// select only elements that are > 2.5
print_r(
array_filter($origarray1, function ($a) { return $a > 2.5; })
);
?>
</pre>
Result:
Array
(
[0] => 2
[1] => 2
[2] => 3
)
Array
(
[0] => 2
[1] => 2
[2] => 3
)
0 => 2.4
1 => 2.6
2 => 3.5
Array
(
[0] => 4.8
[1] => 5.2
[2] => 10.5
)
Array
(
[1] => 2.6
[2] => 3.5
)
Difference between array_filter() and array_map()?
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>
Why does this code use array_filter and array_map to filter an array of integers?
There would be no difference at all if you use the second one as a replacement of first one.
Why: This is due to behaviour of intval
function.
intval Returns integer value of variable on success, or 0 on failure. Empty arrays return 0, non-empty arrays return 1.
Point to be noticed: 0
is considered as false, and any other non-zero integer value considered as true in PHP.
array_filter
filters data based on return value of callable function which should be either true
of false
.
Now in your situation you're calling array_filter
in two manners.
array_filter( array_map( 'intval', (array) $_POST['product_ids'] ) )
- In this you're passing an array of integers to
array_filter
asarray_map
will loop over array and convert each value to corresponding integer by callingintval
function. - Now as there is no parameter passed in
array_filter
so by defaultempty
function will be used and only numeric but not zero(0
) values remains.
array_filter( (array) $_POST['product_ids'], 'intval' )
- In this you are calling
array_filter
butintval
as callable function, which will convert each value to corresponding integer. Main catch is here, if corresponding value is 0 then it will be false, otherwise true, which is equivalent toempty
function in this case.
Note: This doesn't apply to other functions and would not create same results. See this by comparing intval
and is_string
function.
// Input data
$entry = [
0 => 'foo',
1 => false,
2 => -1,
3 => null,
4 => '',
5 => '0',
6 => 0,
];
// comparison for intval function
print_r(array_filter( array_map( 'intval', $entry ) ));
print_r(array_filter( $entry, 'intval' ));
Output:
Array
(
[2] => -1
)
Array
(
[2] => -1
)
// but if you try another function like is_string
print_r(array_filter( array_map( 'is_string', $entry ) ));
print_r(array_filter( $entry, 'is_string' ));
Output:
Array
(
[0] => 1
[4] => 1
[5] => 1
)
Array
(
[0] => foo
[4] =>
[5] => 0
)
array_walk or array_map?
You don't need it to return an array.
Instead of:
$newArray = array_function_you_are_looking_for($oldArray, $funcName);
It's:
$newArray = $oldArray;
array_walk($newArray, $funcName);
Why does the function signature differ between array_map and array_filter/array_reduce?
Does array_map take an array as the last parameter simply because you can feed as many arrays as you want (variadic)?
Yes; only the last parameter in a method signature can be variadic.
Does the ability to feed an arbitrary number of arrays through the callback function of array_map outweigh having more uniform function signatures?
Essentially, this is asking if array_map
should accept multiple arrays. There are good use cases for allowing for calling array_map
with multiple arrays; below is an example from the PHP array_map
guide that I've slightly modified:
<?php
function showLanguages($n, $s, $g)
{
return("The number $n is called $s in Spanish and $g in German.");
}
$a = array(1, 2, 3, 4, 5);
$b = array("uno", "dos", "tres", "cuatro", "cinco");
$c = array("eins", "zwei", "drei", "vier", "funf");
$d = array_map("showLanguages", $a, $b, $c);
print_r($d);
What if array_map were changed to have a multidimensional array as the first argument? While it would technically make the function signatures more uniform, it would actually add some additional problems.
The underlying code would not only have to validate that the first argument is an array, it would have to validate that it's an array of arrays. That would make it essentially be a different kind of parameter than just an array, so it would still be a different method signature than the other array_* methods.
If you really wanted to have the callback as the last argument, you could use a modified function that removes the last element, move it to the first argument, then call array_map on that. You would lose all type-hinting, though, so it'd be harder to use.
/*
* Accepts a variable number of arrays as the first N arguments, takes a callback as the last argument
*/
function map()
{
$args = func_get_args();
$callback = array_pop($args);
array_unshift($args, $callback);
return call_user_func_array("array_map", $args);
}
Remove element from array using array_map
I think array_map is not designed for your needs, because it's apply a callback for each element of your array. But array_filter does :
$array = array_filter($array, function($e) {
return is_numeric($e);
});
Or even shorter :
$array = array_filter($array, 'is_numeric');
How to pass standard php functions to array_map and array_filter?
You need to pass the function (user-defined OR builtin) name as a string in the parameter of array_map function.
Do the following:
$result = array_map('boolval', $elements);
array_walk vs array_map vs foreach
array_walk
doesn't look at what result function gives. Instead it passes callback a reference to item value. So your code for it to work needs to be
function walk_trim(&$value) {
$value = trim($value);
}
foreach
doesn't store changed values itself either. Change it to
foreach ($input3 as &$in) {
$in = trim($in);
}
Read more about references.
Display array result in html table using array_walk or array_map
You are confusing where you put the PHP code.
Try with this:
<?php
function myfunction($value, $key) {
echo '<tr><td>'.$value.'</td><td>Edit</td></tr>';
}
$a = array("a" => "user1", "b" => "user2", "c" => "user3");
$users = $this->db->get('user')->result();
echo '<table><tr><th>Name</th><th>Edit</th></tr><tbody>';
array_walk($a, "myfunction");
echo '</tbody></table>';
?>
Related Topics
Check If PHP-Page Is Accessed from an iOS Device
How to Chain Method on a Newly Created Object
Least Memory Intensive Way to Read a File in PHP
How to Build a JSON Array from MySQL Database
How to Limit File Upload Type File Size in PHP
Can You Add an If Statement in Order By
Laravel 5.4 on PHP 7.0: Pdo Exception - Could Not Find Driver (Mysql)
How to Generate Random 64-Bit Value as Decimal String in PHP
In PHP, Is There a Short Way to Compare a Variable to Multiple Values
How to Install/Enable the PHP Phar Extension
PHP Decoding and Encoding JSON with Unicode Characters
Two Simultaneous Ajax Requests Won't Run in Parallel
What Does This Symbol Mean in PHP <=
How to Get Ruby Syntax Highlighting in PHPstorm
Geo-Search (Distance) in PHP/MySQL (Performance)