究竟是什么区别array_map,array_walk和array_filter.我从文档中看到的是,您可以传递一个回调函数来对提供的数组执行操作.但我似乎没有发现它们之间有任何特别的区别.
他们做同样的事吗?
它们可以互换使用吗?
如果它们完全不同,我将非常感谢您的帮助.
Art*_*cto 544
array_map可以不改变输入数组内的值array_walk; 特别是,array_map永远不要改变它的论点.array_map无法使用数组键操作,array_walk可以.array_map返回一个新数组,array_walk只返回true/ array_walk.因此,如果您不想通过遍历一个数组来创建数组,则应该使用array_map.array_walk也可以接收任意数量的数组,它可以并行迭代它们,而array_walk只能在一个数组上运行.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>
Run Code Online (Sandbox Code Playgroud)
结果:
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
)
Run Code Online (Sandbox Code Playgroud)
Ken*_*ins 89
将函数映射到数据数组的想法来自函数式编程.您不应该将其array_map视为foreach在数组的每个元素上调用函数的循环(即使它是如何实现的).应该考虑将函数独立地应用于数组中的每个元素.
理论上,诸如函数映射之类的事情可以并行完成,因为应用于数据的函数应仅影响数据而不影响全局状态.这是因为array_map可以选择将函数应用于项目的任何顺序(即使在PHP中它没有).
array_walk另一方面,它与处理数据数组完全相反.它不是单独处理每个项目,而是使用state(&$userdata)并且可以在适当的位置编辑项目(很像foreach循环).由于每次项目都$funcname应用了它,它可能会改变程序的全局状态,因此需要一种正确的处理项目的方法.
回到PHP版本,array_map并且array_walk几乎完全相同,除了array_walk让您更好地控制数据的迭代,通常用于"更改"数据,而不是返回一个新的"已更改"数组.
array_filter实际上是array_walk(或array_reduce)的应用程序,它或多或少只是为方便起见而提供的.
Ste*_*ker 39
从文档中,
bool array_walk(array&$ array,callback $ funcname [,mixed $ userdata])< - return bool
array_walk接受一个数组和一个函数F,并通过替换每个元素x来修改它F(x).
array array_map(callback $ callback,array $ arr1 [,array $ ...])< - 返回数组
array_map执行完全相同的操作,除了不是在就地修改它将返回带有转换元素的新数组.
array array_filter(array $ input [,callback $ callback])< - return array
带有函数的array_filterF,而不是转换元素,将删除任何F(x)不正确的元素
War*_*rbo 21
其他答案很好地演示了array_walk(就地修改)和array_map(返回修改后的副本)之间的区别.但是,他们并没有真正提到array_reduce,这是理解array_map和array_filter的一种有启发性的方式.
array_reduce函数接受一个数组,一个双参数函数和一个'accumulator',如下所示:
array_reduce(array('a', 'b', 'c', 'd'),
'my_function',
$accumulator)
Run Code Online (Sandbox Code Playgroud)
使用给定的函数,数组的元素一次一个地与累加器组合.上述调用的结果与执行此操作相同:
my_function(
my_function(
my_function(
my_function(
$accumulator,
'a'),
'b'),
'c'),
'd')
Run Code Online (Sandbox Code Playgroud)
如果您更喜欢用循环来思考,那就像执行以下操作(当array_reduce不可用时,我实际上将其用作后备):
function array_reduce($array, $function, $accumulator) {
foreach ($array as $element) {
$accumulator = $function($accumulator, $element);
}
return $accumulator;
}
Run Code Online (Sandbox Code Playgroud)
这个循环版本清楚地说明了为什么我将第三个参数称为"累加器":我们可以使用它来累积每次迭代的结果.
那么这与array_map和array_filter有什么关系呢?事实证明,它们都是一种特殊的array_reduce.我们可以像这样实现它们:
array_map($function, $array) === array_reduce($array, $MAP, array())
array_filter($array, $function) === array_reduce($array, $FILTER, array())
Run Code Online (Sandbox Code Playgroud)
忽略array_map和array_filter以不同顺序获取其参数的事实; 这只是PHP的另一个怪癖.重要的一点是,除了我称之为$ MAP和$ FILTER的函数之外,右侧是相同的.那么,它们看起来像什么?
$MAP = function($accumulator, $element) {
$accumulator[] = $function($element);
return $accumulator;
};
$FILTER = function($accumulator, $element) {
if ($function($element)) $accumulator[] = $element;
return $accumulator;
};
Run Code Online (Sandbox Code Playgroud)
如您所见,两个函数都接受$ accumulator并再次返回.这些功能有两个不同之处:
请注意,这远非无用的琐事; 我们可以用它来提高我们的算法效率!
我们经常可以看到这两个例子的代码:
// Transform the valid inputs
array_map('transform', array_filter($inputs, 'valid'))
// Get all numeric IDs
array_filter(array_map('get_id', $inputs), 'is_numeric')
Run Code Online (Sandbox Code Playgroud)
使用array_map和array_filter而不是循环使这些示例看起来非常好.但是,如果$ input很大,则效率非常低,因为第一次调用(map或filter)将遍历$ input并构建一个中间数组.这个中间数组直接传递给第二个调用,它将遍历整个事件,然后中间数组将需要进行垃圾回收.
我们可以通过利用array_map和array_filter都是array_reduce的例子来摆脱这个中间数组.通过组合它们,我们只需要在每个示例中遍历$ input:
// Transform valid inputs
array_reduce($inputs,
function($accumulator, $element) {
if (valid($element)) $accumulator[] = transform($element);
return $accumulator;
},
array())
// Get all numeric IDs
array_reduce($inputs,
function($accumulator, $element) {
$id = get_id($element);
if (is_numeric($id)) $accumulator[] = $id;
return $accumulator;
},
array())
Run Code Online (Sandbox Code Playgroud)
注意:我上面的array_map和array_filter的实现不会像PHP一样,因为我的array_map一次只能处理一个数组,而我的array_filter不会使用"empty"作为它的默认$函数.此外,两者都不会保留密钥.
让它们表现得像PHP一样并不困难,但我觉得这些复杂性会使核心思想更难发现.
| 归档时间: |
|
| 查看次数: |
160722 次 |
| 最近记录: |