22

我查看了 web 中的类似主题以及堆栈溢出,但可以清楚地了解这个主题。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_filterarray_map? 实现 an 的功能。

4

5 回答 5

30

所有三个,array_filterarray_maparray_walk,都使用回调函数循环遍历数组,就像foreach循环使用$key => $value对循环遍历$array一样。 在这篇文章中,我将引用原始数组,传递给上述函数,如$array,循环中当前项目的索引,作为$key,以及当前项目的值在循环中,作为$value

array_filter 类似于MySQL 的 SELECT 查询,它选择记录但不修改它们。
array_filter 的回调传递了当前循环项的$value,并且无论回调返回什么都被视为布尔值。
如果为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接受多个数组作为参数。如果指定了一个数组,则循环中当前项的 $value 被发送到回调。如果使用两个或多个数组,则所有数组都需要首先通过 array_values 传递,如文档中所述:

如果数组参数包含字符串键,则当且仅当仅传递一个数组时,返回的数组将包含字符串键。如果传递了多个参数,则返回的数组始终具有整数键

循环第一个数组并将其值作为其第一个参数传递给回调,如果指定了第二个数组,则它也将被循环并将其值作为第二个参数发送给回调,依此类推对于每个附加参数,依此类推。
如果数组的长度不匹配,则使用最大的数组,如文档中所述:

通常在使用两个或多个数组时,它们应该是等长的,因为回调函数是并行应用到相应的元素上的。如果数组的长度不等,较短的数组将用空元素扩展以匹配最长的长度。

每次调用回调时,都会收集返回值。仅在使用一个数组时保留键,并且 array_map 返回结果数组。如果使用两个或更多数组,则键会丢失,而是返回一个填充有回调结果的新数组。array_map 只向回调发送当前项目的 $value 而不是它的 $key。如果您也需要密钥,您可以array_keys($array)作为附加参数传递,然后回调将同时接收 $key 和 $value。
但是,当使用多个数组时,原始键将以与 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 影响某些内容,您需要引用 &$value 以便您拥有要修改或使用全局数组的内容。或者,如果您不想污染全局范围,可以使用 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>
于 2013-11-05T09:16:09.270 回答
6

array_filter返回函数返回 true 的原始数组的元素。

array_map返回对原始数组的所有元素调用函数的结果数组。

我想不出你可以用一个代替另一个的情况。

于 2013-10-31T05:29:49.883 回答
4

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
)
于 2014-12-09T12:51:13.923 回答
4

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新数组,这是因为数组是通过引用传递的。

于 2017-03-23T11:16:33.680 回答
0
  • array_map 没有附带影响,而 array_map 从不更改其参数。
  • array_map/array_walk 的结果数组与参数具有相同数量的元素;array_filter 根据过滤函数仅选择数组元素的子集。它确实保留了密钥。

例子:

<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
)
于 2013-10-31T05:30:28.013 回答