我在php中使用地图,如下所示:
function func($v) {
return $v * 2;
}
$values = array(4, 6, 3);
$mapped = array_map(func, $values);
var_dump($mapped);
是否可以获取函数中值的索引?
另外-如果我正在编写需要索引的代码,是否应该使用for循环而不是map?
Answers:
当然可以,在 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()
任意数量的参数:)
array_keys
将保持与原始数组相同的顺序。因此,您可能最终将键映射到错误的值。安全的方法是仅将array_keys
用作第二个参数,array_map
然后使用use
语句将数组传递给闭包。
在匿名数组上映射匿名函数时,无法访问键:
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) { /* ... */ });
很简单的:
只有array_map功能:没有索引键!
$params = [4,6,2,11,20];
$data = array_map(function($v) { return ":id{$v}";}, $params);
array (size=5)
0 => string ':id4' (length=4)
1 => string ':id6' (length=4)
2 => string ':id2' (length=4)
3 => string ':id11' (length=5)
4 => string ':id20' (length=5)
现在,与array_keys结合:
$data = array_map(
function($k) use ($params) { return ":id{$k}_${params[$k]}"; },
array_keys($params)
);
array (size=5)
0 => string ':id0_4' (length=6)
1 => string ':id1_6' (length=6)
2 => string ':id2_2' (length=6)
3 => string ':id3_11' (length=7)
4 => string ':id4_20' (length=7)