将匿名函数映射到匿名数组时,无法访问键:
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);
一次性功能
我们可以使用函数范围来防止破坏现有名称,但必须添加一个额外的“使用”层:
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) { /* ... */ });