Tyler Nichol
Tyler Nichol

Reputation: 655

merge recursive on inner arrays of multidimensional array php

I have a multidimensional array that looks like such:

 Array
(
[0] => Array
    (
        [email] => [email protected]
        [added] => style-narcotics
    )

[1] => Array
    (
        [email] => [email protected]
        [added] => style-edm
    )

[2] => Array
    (
        [email] => [email protected]
        [added] => style-codeine
    )

[3] => Array
    (
        [email] => [email protected]
        [added] => style-food
    )
  )

I want to merge all the inner arrays combining the "added" key like such:

Array
(
[0] => Array
    (
        [email] => [email protected]
        [added] => array(
                        [0]=>style-narcotics
                        [1]=>style-edm
                        )
    )



[1] => Array
    (
        [email] => [email protected]
        [added] => array(
                        [0]=>style-codeine
                        [1]=>style-food
    )

  )

I have tried merge array recursive in different forms and call_user_func but it doesnt cut it. Any advice? Thanks!

Upvotes: 2

Views: 327

Answers (2)

axiac
axiac

Reputation: 72226

A simple solution that uses 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);

The same logic as above but with an explicit iteration over the input array (the code is a couple of lines shorter):

$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);

Upvotes: 1

RomanPerekhrest
RomanPerekhrest

Reputation: 92854

I would call it "grouping", but not "merging".
Use the following approach with array_walk and array_values functions:

$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));

The output:

Array
(
    [0] => Array
        (
            [email] => [email protected]
            [added] => Array
                (
                    [0] => style-narcotics
                    [1] => style-edm
                )

        )

    [1] => Array
        (
            [email] => [email protected]
            [added] => Array
                (
                    [0] => style-codeine
                    [1] => style-food
                )
        )
)

Upvotes: 3

Related Questions