PHP:是否可以在array_map函数中获取索引?


83

我在php中使用地图,如下所示:

function func($v) {
    return $v * 2;
}

$values = array(4, 6, 3);
$mapped = array_map(func, $values);
var_dump($mapped);

是否可以获取函数中值的索引?

另外-如果我正在编写需要索引的代码,是否应该使用for循环而不是map?

Answers:


209

当然可以,在 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);

20
很酷的答案,没有意识到您可以将额外的参数传递给array_map()ped方法。每天学些新东西!
GordonM

1
@Gordon是的,您可以提供array_map()任意数量的参数:)
Aron Rotteveel

13
这是一种非常冒险的方法,因为PHP不保证返回的键array_keys将保持与原始数组相同的顺序。因此,您可能最终将键映射到错误的值。安全的方法是仅将array_keys用作第二个参数,array_map然后使用use语句将数组传递给闭包。
user487772 2015年

12
坦白地说,我不明白为什么PHP没有提供将每个元素的键作为回调的第二个参数的map函数。
流感

1
@flu PHP无缘无故获得不良语言称号。
xZero

9

在匿名数组上映射匿名函数时,无法访问键:

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) { /* ... */ });

0

很简单的:

只有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)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.