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

Oll*_*ass 62 php arrays iteration dictionary loops

我在php中使用地图如下:

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

$values = array(4, 6, 3);
$mapped = array_map(func, $values);
var_dump($mapped);
Run Code Online (Sandbox Code Playgroud)

是否有可能获得函数中值的索引?

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

Aro*_*eel 172

当然,你可以在...的帮助下 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);
Run Code Online (Sandbox Code Playgroud)

  • 很酷的回答,没有意识到你可以将额外的参数传递给array_map()ped方法.每天学些新东西! (18认同)
  • 这是一种非常冒险的方法,因为PHP不保证`array_keys`返回的键将保持与原始数组中的顺序相同.因此,您可能最终将键映射到错误的值.安全的方法是只使用`array_keys`作为`array_map`的第二个参数,然后使用`use`语句将数组传递给closure. (12认同)
  • 我坦率地不明白为什么PHP没有map函数提供每个元素的键作为回调的第二个参数. (9认同)
  • @flu PHP 没有无缘无故地获得不良语言的称号。 (3认同)
  • 我同意在这种情况下最好不要使用 array_keys 。相反,我们可以使用以下方式获取索引: range(0, count($array)-1) (3认同)
  • @TimBezhashvyly 你能通过 PHP 文档的链接来充实这一点吗?http://php.net/manual/en/function.array-keys.php 没有说任何关于不保证顺序的事情。 (2认同)

Eva*_*van 13

无法在array_map回调中访问索引。如果您使用顺序数字索引,则可以使用递增静态变量:

$values = ["one", "two", "three"];

$mapped = array_map(function ($value) {
    static $i = 0;
    $result = "Index: $i, Value: $value";
    $i++;
    return $result;
}, $values);

print_r($mapped);
Run Code Online (Sandbox Code Playgroud)

导致:

Array
(
    [0] => Index: 0, Value: one
    [1] => Index: 1, Value: two
    [2] => Index: 2, Value: three
)
Run Code Online (Sandbox Code Playgroud)

使用此方法时,重要的是使用匿名函数作为回调,并且永远不要重用该匿名函数,以避免引用 array_map 外部的相同静态变量。


War*_*rbo 8

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

array_map(
    function($val) use ($foo) { /* ... */ },
    array(key1 => val1,
          key2 => val2,
          /* ... */));
Run Code Online (Sandbox Code Playgroud)

array_reduce也无法访问密钥.array_walk可以访问键,但是数组是通过引用传递的,这需要一层间接.

一些解决方案是:

对数组

这很糟糕,因为我们正在更改原始数组.此外,样板"array()"调用随着数组的长度线性增加:

array_map(
    function($pair) use ($foo) {
        list($key, $val) = $pair;
        /* ... */
    },
    array(array(key1, val1),
          array(key2, val2),
          /* ... */));
Run Code Online (Sandbox Code Playgroud)

临时变量

我们正在对原始数组进行操作,并且样板文件是常量,但我们可以轻松地破坏现有变量:

$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);
Run Code Online (Sandbox Code Playgroud)

一次性功能

我们可以使用函数范围来防止破坏现有名称,但必须添加额外的"使用"层:

call_user_func(
    function($arr) use ($foo) {
        return array_map(function($key, $val) use ($foo) { /* ... */ },
                         array_keys($arr),
                         $arr);
    },
    array(key1 => val1,
          key2 => val2,
          /* ... */));
Run Code Online (Sandbox Code Playgroud)

多参数一次性功能

我们定义了我们在原始范围内映射的函数,以防止"使用"样板:

call_user_func(
    function($f, $arr) {
        return array_map($f, array_keys($arr), $arr);
    },
    function($key, $val) use ($foo) { /* ... */ },
    array(key1 => val1,
          key2 => val2,
          /* ... */));
Run Code Online (Sandbox Code Playgroud)

新功能

有趣的是要注意的是,我们的最后一次性功能有一个很好的通用签名,看起来很像array_map.我们可能想给它一个名字并重复使用它:

function array_mapk($f, $arr) {
    return array_map($f, array_keys($arr), $arr);
}
Run Code Online (Sandbox Code Playgroud)

我们的应用程序代码变为:

array_mapk(
    function($key, $val) use ($foo) { /* ... */ },
    array(key1 => val1,
          key2 => val2,
          /* ... */));
Run Code Online (Sandbox Code Playgroud)

间接阵列行走

写上面的时候我忽略了array_walk,因为它要求它的参数通过引用传递; 但是,我已经意识到使用call_user_func很容易解决这个问题.我认为这是目前为止最好的版本:

call_user_func(
    'array_walk',
    array(key1 => val1,
          key2 => val2,
          /* ... */),
    function($val, $key) use ($foo) { /* ... */ });
Run Code Online (Sandbox Code Playgroud)


小智 5

这是一个有点旧的线程,但和你们中的许多人一样,我正在使用array_keys

array_map(function($id, $name) {
    print '<option value="'.$id.'">'.$name.'</option>';
}, array_keys($array), array_values($array));
Run Code Online (Sandbox Code Playgroud)

编辑:use您可以在函数的第二个参数中添加两个数组,而不是关键字arrray_map。我认为不需要解释,代码非常简单。