PHP:我可以在array_map函数中获取索引吗?

2022-08-30 07:30:07

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

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

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

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

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


答案 1

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

答案 2

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

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