Объединить массивы и сгруппировать
Прошу помощи с объединением двух массивов:
Array(
[1] => Array(
[id] => 1
[name] => name1
[surname] => surname1
)
[2] => Array(
[id] => 2
[name] => name2
[surname] => surname2
)
[4] => Array(
[id] => 3
[name] => name3
[surname] => surname3
)
)
Array(
[0] => Array(
[id] => 1
[result] => 5
)
[1] => Array(
[id] => 2
[result] => 12
)
[2] => Array(
[id] => 3
[result] => 19
)
[3] => Array(
[id] => 1
[result] => 0
)
[4] => Array(
[id] => 3
[result] => 0
)
[5] => Array(
[id] => 2
[result] => 6
)
)
Я хочу получить новый массив, где будут группы равные самому большому (в данном случае 2 группы) количеству повторений id во втором массиве и одна группа с общим значением. Пример результата:
Array(
[Total] => Array(
[0] => Array(
[id] => 1
[name] => name1
[surname] => surname1
[result] => 5
)
[1] => Array(
[id] => 2
[name] => name2
[surname] => surname2
[result] => 18
)
[2] => Array(
[id] => 3
[name] => name3
[surname] => surname3
[result] => 19
)
)
[group 1] => Array(
[0] => Array(
[id] => 1
[name] => name1
[surname] => surname1
[result] => 5
)
[1] => Array(
[id] => 2
[name] => name2
[surname] => surname2
[result] => 12
)
[2] => Array(
[id] => 3
[name] => name3
[surname] => surname3
[result] => 19
)
)
[group 2] => Array(
[0] => Array(
[id] => 1
[name] => name1
[surname] => surname1
[result] => 5
)
[1] => Array(
[id] => 2
[name] => name2
[surname] => surname2
[result] => 6
)
[2] => Array(
[id] => 3
[name] => name3
[surname] => surname3
[result] => 0
)
)
)
Вот моя функция, которая их объединяет:
public function grouping() {
$arr1 = [...];
$arr2 = [...];
$groupNumber = 0;
$finalArr[Total] = [];
foreach ($arr1 as $player) {
$groupNumber = 0;
$allResult = 0;
foreach ($arr2 as $result) {
if ($result['id'] === $player['id']) {
$raceNumber++;
$allResult += $result['result'];
$finalArr["group $groupNumber"][] = $player + ['result' => $result['result']];
}
}
$finalArr[ALL_RACES][] = $player + ['result' => $allResult];
}
return $finalArr;
}
Проблема тут как минимум во вложенном цикле, который я не знаю как убрать. Я пытался использовать array_column на первый массив, чтобы ключ был равным id и я мог вызывать элемент по нему, но тогда у меня появляется проблема с тем, что я не знаю как вычислить количество повторений id во втором массиве и не могу воссоздать нужный мне результат.
Ответы (1 шт):
У вас второй foreach проверяет все элементы массива $arr2 на наличие совпадения id с текущим элементом из $arr1, даже если совпадение уже найдено. Это приводит к тому, что один и тот же элемент из $arr1 может попадать в разные группы, что не соответствует вашей задаче. Нужно прерывать второй цикл сразу после нахождения первого совпадения.
public function grouping() {
$arr1 = [...];
$arr2 = [...];
// Step 1: Создайте временный массив для хранения всех результатов для каждого ID
$tempArr = [];
foreach ($arr2 as $result) {
$id = $result['id'];
if (!isset($tempArr[$id])) {
$tempArr[$id] = [];
}
$tempArr[$id][] = $result['result'];
}
// Step 2: Найдите идентификаторы с наибольшим количеством вхождений в $arr2
$count = array_count_values(array_column($arr2, 'id'));
arsort($count);
$maxCount = reset($count);
$ids = array_keys(array_filter($count, function ($value) use ($maxCount) {
return $value == $maxCount;
}));
// Step 3: Создание финального массива с общей группой и группами с наибольшим количеством вхождений.
$finalArr = ['Total' => [],];
foreach ($ids as $id) {
$finalArr["group $id"] = [];
}
// Step 4: Добавление элементов в группы в $finalArr
foreach ($arr1 as $player) {
$id = $player['id'];
$groupAdded = false;
// Добавление в общую группу
$allResult = 0;
foreach ($tempArr[$id] as $result) {
$allResult += $result;
}
$finalArr['Total'][] = $player + ['result' => $allResult];
// Добавление в группу с наибольшим количеством вхождений
if (in_array($id, $ids)) {
foreach ($tempArr[$id] as $result) {
if (!$groupAdded) {
$finalArr["group $id"][] = $player + ['result' => $result];
$groupAdded = true;
} else {
end($finalArr["group $id"]);
$key = key($finalArr["group $id"]);
$finalArr["group $id"][$key]['result'] += $result;
}
}
}
}
return $finalArr;
}