array_map函数如何访问数组的键?

5

我需要遍历一个类似这样的数组:

$myArray = array(
  'key1' => array('subkey' => 'subvalue'),
  'key2' => array('subkey' => 'subvalue'),
)

我希望你能够为每个嵌套的关联数组添加一个键值对,该键值对基于外部键,如下所示:

$myNewArray = array(
  'key1' => array('subkey' => 'subvalue', 'newkey' => 'only for key1'),
  'key2' => array('subkey' => 'subvalue'),
)

理想情况下,我正在寻找类似于以下内容的东西:
$myNewArray = array_map(function($key, $value) {
    if ($key == 'key1') {
        $value['newkey'] = 'only for key1';
    }
    return $value;
}, $myArray);

然而,这显然行不通,因为callback只给了一个参数而不是两个。我可以这样做:
$myNewArray = array_map(function($key, $value) {
    if ($key == 'key1') {
        $value['newkey'] = 'only for key1';
    }
    return WHAT??
}, array_keys($myArray), $myArray);

然而,我在这里返回什么呢?它似乎总是构造一个新的数组,即丢弃我的字符串键(key1key2),而单个数组的array_map()会保留它们。
我可以使用array_walk(),但它有一个相当奇怪的API(颠倒的参数顺序,通过引用传递数组等),因此通常情况下,我更喜欢使用array_map()来实现。它可以吗?
2个回答

3
我怕array_walk()就是做这件事的方法。
如果你不喜欢array_walk(),坚持使用array_map(),那么也可以。它涉及到同时使用array_keys()array_values()array_combine(),虽然冗长且难看,但是可行的:
$myNewArray = array_combine(
    array_keys($myArray),
    array_map(
        function($key, $value) {
            if ($key == 'key1') {
                $value['newkey'] = 'only for key1';
            }
            return $value;
        },
        array_keys($myArray),
        array_values($myArray)     // can omit array_values() and use $myArray
    )
);

您也可以使用array_reduce()来完成,但这同样是一团糟:
$myNewArray = array_reduce(
    array_keys($myArray),
    function (array $carry, $key) use ($myArray) {
        $value = $myArray[$key];
        if ($key == 'key1') {
            $value['newkey'] = 'only for key1';
        }
        $carry[$key] = $value;
        return $carry;
    },
    array()
);

我希望你的条件比 $key == 'key1' 更复杂,因为仅为此编写复杂遍历并不值得。难道直接访问正确的元素并修改它不是更容易吗?
$myArray['key1']['newkey'] = 'only for key1';

是的,转换远比这个复杂,我只是给出了展示挑战的最小示例。感谢您的回答,第一种方法实际上对我来说看起来并不太丑陋,尽管array_walk()方法肯定会更短。我只是不喜欢通过引用传递数组。 - Borek Bernard

1

array_map 只传递值,而不是键。 array_walkarray_map 非常相似。只需将值定义为引用即可。它接受键,而 array_map 不接受。此外,这会修改 $myArray

array_walk($myArray, function(&$value, $key) {
    if ($key == 'key1') {
        $value['newkey'] = 'only for key1';
    }
});

根据 PHP 手册,似乎有一个使用 array_keys 作为另一个数组的 array_map 方法:

$myNewArray = array_combine(array_keys($myArray), array_map(function($key, $value) {
    if ($key == 'key1') {
        $value['newkey'] = 'only for key1';
    }
    return  $value;
}, array_keys($myArray), $myArray));

是的,这个可以工作,但是正如你的例子所示,API 很令人困惑,很容易犯错 - 在你的例子中 $myNewArray 将会是 true :) 但我明白了,谢谢。 - Borek Bernard
我刚刚注意到当我在使用array_map时。已编辑。 - AbraCadaver
你的第二个例子将返回一个关联数组的数组,这与仅有的关联数组不同。 - Borek Bernard
修复后,代码变得越来越长了... 不管它是否令人困惑,array_walk 是正确和标准的方法。 - AbraCadaver

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接