У меня есть многомерный массив, который выглядит так:
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_walk
и array_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);