在多维数组php的内部数组上递归合并


merge recursive on inner arrays of multidimensional array php

我有一个看起来像这样的多维数组:

 Array
(
[0] => Array
    (
        [email] => email1@gmail.com
        [added] => style-narcotics
    )
[1] => Array
    (
        [email] => email1@gmail.com
        [added] => style-edm
    )
[2] => Array
    (
        [email] => email2@gmail.com
        [added] => style-codeine
    )
[3] => Array
    (
        [email] => email2@gmail.com
        [added] => style-food
    )
  )

我想合并所有内部数组,组合"添加"的密钥,比如:

Array
(
[0] => Array
    (
        [email] => email1@gmail.com
        [added] => array(
                        [0]=>style-narcotics
                        [1]=>style-edm
                        )
    )

[1] => Array
    (
        [email] => email2@gmail.com
        [added] => array(
                        [0]=>style-codeine
                        [1]=>style-food
    )
  )

我尝试过不同形式的递归合并数组和call_user_func,但它并不能解决问题。有什么建议吗?谢谢

我称之为"分组",而不是"合并"
array_walkarray_values函数使用以下方法:

$grouped = [];
// $arr is your initial array
array_walk($arr, function($v) use (&$grouped){
    if (array_key_exists($v["email"], $grouped)) {
        $grouped[$v["email"]]["added"][] = $v["added"];
    } else {
        $v["added"] = [$v["added"]];
        $grouped[$v["email"]] = $v;
    }
});
print_r(array_values($grouped));

输出:

Array
(
    [0] => Array
        (
            [email] => email1@gmail.com
            [added] => Array
                (
                    [0] => style-narcotics
                    [1] => style-edm
                )
        )
    [1] => Array
        (
            [email] => email2@gmail.com
            [added] => Array
                (
                    [0] => style-codeine
                    [1] => style-food
                )
        )
)

使用array_reduce():的简单解决方案

$output = array_reduce(
    $input,
    function (array $carry, array $item) {
        $email = $item['email'];
        if (! isset($carry[$email])) {
            // It's a new email, make room for it in the output
            $carry[$email] = array('email' => $email, 'added' => array(), );
        }
        // Add the value of $item['added'] into the existing array
        $carry[$email]['added'][] = $item['added'];
        return $carry;
    },
    array()
);
// Output is indexed by email addresses. If you need numeric keys then...
$output = array_values($output);

与上面的逻辑相同,但在输入数组上有一个显式迭代(代码短了几行):

$output = array();
foreach ($input as $item) {
    $email = $item['email'];
    if (! isset($carry[$email])) {
        // It's a new email, make room for it in the output
        $carry[$email] = array('email' => $email, 'added' => array(), );
    }
    // Add the value of $item['added'] into the existing array
    $carry[$email]['added'][] = $item['added'];
}
$output = array_values($output);