Объединить массивы и сгруппировать

Рейтинг: 1Ответов: 1Опубликовано: 25.03.2023

Прошу помощи с объединением двух массивов:

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 во втором массиве и не могу воссоздать нужный мне результат.

Ответы

▲ 0

У вас второй 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;
}