Я просмотрел похожие темы в Интернете, а также переполнение стека, но я мог ясно понять это в своей голове. Разница между array_map, array_walk и 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; })); ?>
Вышеприведенный код возвращает мне фильтрованный массив, значение которого составляет> 2,5 . Могу ли я достичь того, что делает array_filter
с array_map
?.
Все три массива array_filter , array_map и array_walk используют функцию обратного вызова для циклического преобразования массива точно так же, как цикл foreach loop loop через массив $, используя пары $ key => $ value .
На протяжении всего этого сообщения я буду ссылаться на исходный массив, переданный вышеупомянутым функциям, как $ array , index, текущего элемента в цикле, как $ key и значение текущего элемента в цикле, как $ value .
array_filter сравнивается с запросом SELECT MySQL, который SELECTs записывает, но не модифицирует.
Обратный вызов array_filter передается значение $ текущего элемента цикла, и все возвращаемые обратные вызовы рассматриваются как логические.
Если значение true , элемент включается в результаты.
Если false , элемент исключается из результатов.
Таким образом, вы можете:
<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 принимает несколько массивов в качестве аргументов. Если задан один массив, значение $ current текущего элемента в цикле отправляется на обратный вызов. Если используются два или более массива, все массивы должны быть сначала переданы через array_values, как указано в документации :
Если аргумент массива содержит строковые ключи, то возвращаемый массив будет содержать строковые ключи тогда и только тогда, когда передается ровно один массив. Если передано несколько аргументов, возвращаемый массив всегда имеет целые ключи
Первый массив зацикливается, и его значение передается обратному вызову в качестве его первого параметра, и если задан второй массив, он также будет зациклирован и его значение будет отправлено в качестве второго параметра для обратного вызова и так далее и так для каждого дополнительного параметра.
Если длина массивов не соответствует, используется самый большой массив, как указано в документации :
Обычно при использовании двух или более массивов они должны быть одинаковой длины, поскольку функция обратного вызова применяется параллельно с соответствующими элементами. Если массивы имеют неравную длину, более короткие будут расширены пустым элементом, чтобы соответствовать длине самого длинного.
Каждый раз, когда вызывается обратный вызов, возвращается возвращаемое значение. Клавиши сохраняются только при работе с одним массивом, а array_map возвращает результирующий массив. При работе с двумя или несколькими массивами ключи теряются, и вместо этого возвращается новый массив, заполненный результатами обратного вызова. array_map отправляет обратный вызов значение $ текущего элемента, а не его $ key. Если вам нужен ключ, вы можете передать array_keys($array)
в качестве дополнительного аргумента, тогда обратный вызов получит как ключ $, так и значение $.
Однако при использовании нескольких массивов исходные ключи будут потеряны почти так же, как array_values отбрасывает ключи. Если вам нужны ключи, которые нужно сохранить, вы можете использовать array_keys для захвата ключей из исходного массива и array_values для захвата значений из результата array_map или просто использовать результат array_map напрямую, поскольку он уже возвращает значения, тогда объедините два, используя array_combine .
Таким образом, вы можете:
<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 очень похож на foreach($array as $key=>$value)
тем, что обратный вызов отправляется как ключ, так и значение. Он также принимает необязательный аргумент, если вы хотите передать третий аргумент непосредственно обратному вызову.
array_walk возвращает логическое значение, указывающее, успешно ли завершен цикл.
(Мне еще предстоит найти практическое применение)
Обратите внимание, что array_walk не использует обратный вызов. Поскольку array_walk возвращает логическое значение, для того чтобы array_walk повлиял на что-то, вам нужно указать значение & $, чтобы у вас было то, что нужно изменить или использовать глобальный массив. В качестве альтернативы, если вы не хотите загрязнять глобальную область видимости, необязательный третий аргумент array_walk может использоваться для передачи ссылки на переменную, с которой следует писать.
Таким образом, вы можете:
<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>
array_filter
возвращает элементы исходного массива, для которых функция возвращает true.
array_map
возвращает массив результатов вызова функции во всех элементах исходного массива.
Я не могу думать о ситуации, когда вы могли бы использовать ее вместо другой.
array_map
Возвращает массив, содержащий все элементы массива, после применения функции обратного вызова к каждому из них.
например:
$a=array("a","bb","ccd","fdjkfgf"); $b = array_map("strlen",$a); print_r($b); //output Array ( [0] => 1 //like strlen(a) [1] => 2 //like strlen(bb) [2] => 3 //like strlen(ccd) [3] => 7 //like strlen(fdjkfgf) )
тогда как array_filter
возвращает только те элементы массива, для которых функция истинна
пример: удалить значение «bb» из массива
function test_filter($b) { if($b=="bb") { return false; } else { return true; } } $a=array("a","bb","ccd","fdjkfgf"); $b = array_filter($a,"test_filter"); print_r($b); //output Array ( [0] => a //test_filter() return true [2] => ccd //test_filter() return true [3] => fdjkfgf //test_filter() return true )
array_filter
также работает без передаваемой функции (функции), тогда как для array_map
это обязательно.
например
$v = [true, false, true, true, false]; $x = array_filter($v); var_dump($x); array(3) { [0]=> bool(true) [2]=> bool(true) [3]=> bool(true) }
array_walk
изменяет фактический массив, переданный в, тогда как array_filter
и array_map
возвращают новые массивы, это потому, что массив передается по ссылке.
Пример:
<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>
Результат:
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 )