在匿名数组上映射匿名函数时,无法访问密钥:
array_map(
function($val) use ($foo) { /* ... */ },
array(key1 => val1,
key2 => val2,
/* ... */));
array_reduce也无法访问密钥。array_walk可以访问密钥,但数组是通过引用传递的,这需要一个间接层。
一些解决方案是:
对数组
这很糟糕,因为我们正在更改原始数组。另外,样板“array()”调用随数组的长度线性增加:
array_map(
function($pair) use ($foo) {
list($key, $val) = $pair;
/* ... */
},
array(array(key1, val1),
array(key2, val2),
/* ... */));
临时变量
我们正在对原始数组进行操作,并且样板是常量,但是我们可以很容易地删除现有变量:
$i_hope_this_does_not_conflict = array(key1 => val1,
key2 => val2,
/* ... */);
array_map(
function($key, $val) use ($foo) { /* ... */ },
array_keys($i_hope_this_does_not_conflict),
$i_hope_this_does_not_conflict);
unset($i_hope_this_does_not_conflict);
一次性功能
我们可以使用函数范围来防止破坏现有名称,但必须添加一个额外的“use”层:
call_user_func(
function($arr) use ($foo) {
return array_map(function($key, $val) use ($foo) { /* ... */ },
array_keys($arr),
$arr);
},
array(key1 => val1,
key2 => val2,
/* ... */));
多参数一次性功能
我们在原始作用域中定义要映射的函数,以防止“使用”样板):
call_user_func(
function($f, $arr) {
return array_map($f, array_keys($arr), $arr);
},
function($key, $val) use ($foo) { /* ... */ },
array(key1 => val1,
key2 => val2,
/* ... */));
新功能
需要注意的有趣之处在于,我们最后一个单次函数具有漂亮的通用签名,看起来很像array_map。我们可能想给它一个名字并重新使用它:
function array_mapk($f, $arr) {
return array_map($f, array_keys($arr), $arr);
}
然后,我们的应用程序代码将变为:
array_mapk(
function($key, $val) use ($foo) { /* ... */ },
array(key1 => val1,
key2 => val2,
/* ... */));
间接阵列行走
在写上面的内容时,我忽略了array_walk因为它要求通过引用传递其参数;但是,我已经意识到使用call_user_func很容易解决此问题。我认为这是迄今为止最好的版本:
call_user_func(
'array_walk',
array(key1 => val1,
key2 => val2,
/* ... */),
function($val, $key) use ($foo) { /* ... */ });