简体   繁体   中英

Merge 2d array into another 2d array based on a column and create a subarray from related data in another column

I have two arrays:

$arr1 = [
    [
        'id' => 1,
        'name' => 'John',
        'email' => 'j@mail.com'
    ],
    [
        'id' => 2,
        'name' => 'Jane',
        'email' => 'jane@mail.com'
    ]
];

And the second array:

$arr2 = [
    [
        'id' => 1,
        'email' => 'john@yahoo.com'
    ],
    [
        'id' => 2,
        'email' => 'jane@yahoo.com'
    ],
    [
        'id' => 2,
        'email' => 'jane.doe@hotmail.com'
    ],
];

I would like to add all values with the same 'id' from the second array to the first array. The result I expect would be:

$arr3 = [
    [
        'id' => 1,
        'name' => 'John',
        'email' => ['j@mail.com', 'john@yahoo.com']
    ],
    [
        'id' => 2,
        'name' => 'Jane',
        'email' => ['jane@mail.com', 'jane@yahoo.com', 'jane.doe@hotmail.com']
    ]
];

This code will do what you want. It goes through all the entries of $arr2 , looking for matching id values in $arr1 and, where it finds them, adding the email address from $arr2 to the list of emails in $arr1 for that id value:

foreach ($arr2 as $arr) {
    if (($k = array_search($arr['id'], array_column($arr1, 'id'))) !== false) {
        if (is_array($arr1[$k]['email'])) {
            $arr1[$k]['email'][] = $arr['email'];
        }
        else {
            $arr1[$k]['email'] = array($arr1[$k]['email'], $arr['email']);
        }
    }
}

Output:

Array (
    [0] => Array (
        [id] => 1 
        [name] => John
        [email] => Array (
            [0] => j@mail.com
            [1] => john@yahoo.com
        )
    )
    [1] => Array (
        [id] => 2
        [name] => Jane
        [email] => Array (
            [0] => jane@mail.com
            [1] => jane@yahoo.com
            [2] => jane.doe@hotmail.com
        )
    )
)

I agree with @Barmar's comment under the question; it will be more direct/efficient and boast a superior computational time complexity to iterate the second array to populate a lookup array and reference it while iterating the first array versus doing full scans and searches of the first array for every row of the second array.

This implementation forms the lookup array using array destructuring syntax in a body-less foreach() loop. Then another foreach() loop iterates the first array using array destructuring syntax, modifying the rows' email element, and checking if there are any emails to add to the first array's email.

Even if no corresponding row exists in the second array, the first array's email string will be cast as a single-element array for consistency.

Code: ( Demo )

foreach ($arr2 as ['id' => $id, 'email' => $lookup[$id][]]);

foreach ($arr1 as ['id' => $id, 'email' => &$email]) {
    $email = array_merge((array) $email, $lookup[$id] ?? []);
}

var_export($arr1);

The name element does not need to be mentioned during array destructuring because there are no subsequent processes applied to it in the loops.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM