我在php中使用地图如下:
function func($v) { return $v * 2; } $values = array(4, 6, 3); $mapped = array_map(func, $values); var_dump($mapped);
是否有可能获得函数中值的索引?
另外 - 如果我正在编写需要索引的代码,我应该使用for循环而不是map吗?
当然,你可以在...的帮助下 array_keys():
function func($v, $k) { // key is now $k return $v * 2; } $values = array(4, 6, 3); $mapped = array_map(func, $values, array_keys($values)); var_dump($mapped);
在匿名数组上映射匿名函数时,无法访问密钥:
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) { /* ... */ });