Объединение двух и более массивов в один массив по цифровым ключам без дублирования в подмассивах

У меня есть следующий сценарий, состоящий из массивов с числовыми ключами. Мне нужен массив, в котором хранятся все значения массивов, сгруппированные по числовому ключу и без дубликатов. Я не могу сделать их строками, поскольку они являются идентификаторами и должны оставаться числовыми.

Отправная точка:

    Array
    (
        [77] => Array
            (
                [0] => Bold Condensed
                [1] => Bold Condensed 2
                [2] => Bold Condensed 3
            )
    
    )
    Array
    (
        [77] => Array
            (
                [0] => Bold Condensed
            )
    
        [136] => Array
            (
                [0] => Regular
            )
    
    )
    Array
    (
        [77] => Array
            (
                [0] => Bold Condensed (1, 2, 3)
            )
    
        [168] => Array
            (
                [0] => Regular
                [1] => Bold
            )
    
    )

Ожидаемый результат:

Array
(
    [77] => Array
        (
            [0] => Bold Condensed
            [1] => Bold Condensed 2
            [2] => Bold Condensed 3
            [3] => Bold Condensed (1 ,2 ,3)
        )

    [136] => Array
        (
            [0] => Regular
        )

    [168] => Array
        (
            [0] => Regular
            [1] => Bold
        )

)

Пробовал array_merge и array_merge_recursive:

$megaArray = [];

foreach( $arrays as $key => $value) {
  if (array_key_exists($key, $arrays)){
    $megaArray[$key] = array_merge_recursive($value);
  }
}

Что я получаю как с array_merge, так и с array_merge_recursive:

Array
(
    [77] => Array
        (
            [0] => Bold Condensed (1, 2, 3)
        )

    [136] => Array
        (
            [0] => Regular
        )

    [168] => Array
        (
            [0] => Regular
            [1] => Bold
        )

)

Кажется, что и array_merge(), и array_merge_recursive() хранят последнее значение для каждого ключа.

Это условие: array_key_exists($key, $arrays) всегда будет истинным внутри вашего цикла foreach, потому что $arrays — это то, что вы повторяете. Кроме того, поскольку вы передаете только один массив в array_merge_recursive, он просто возвращает его, а не объединяет с чем-либо.

Rob Eyre 22.09.2023 13:48

@ilariaroglieri В ваш вопрос и приведенный выше код встроено противоречие: вы сначала говорите о массивах, а в стартовом коде показаны три отдельных массива. Но затем ваше предложение foreach перебирает структуру $arrays, которая, похоже, состоит из данных трех массивов. Что это такое? Три массива или один массив с тремя вложенными массивами?

lukas.j 22.09.2023 14:51
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
0
3
81
6
Перейти к ответу Данный вопрос помечен как решенный

Ответы 6

Ответ принят как подходящий

Я думаю, вам просто нужна комбинация array_merge и array_unique (поскольку я отмечаю, что у вас нет дубликатов в ваших листовых массивах):

$megaArray = [];

foreach ($arrays as $subArray) {
  foreach ($subArray as $key => $value) {
    if (array_key_exists($key, $megaArray)) {
      $megaArray[$key] = array_unique(array_merge($megaArray[$key], $value));
    } else {
      $megaArray[$key] = $value;
    }
  }
}

Судя по ожидаемому результату, вам нужно одновременно проверить ключ и значения. Я пишу код, который создает точный выходной массив, подобный вашему образцу. Нет нужды говорить, что с помощью функции можно упростить весь процесс, но для понимания принципа ситуации я каждый раз повторяю foreach.

$newarray = array();

//-------------
$array1 = array();
$array1[77][0] = 'Bold Condensed';
$array1[77][1] = 'Bold Condensed 2';
$array1[77][2] = 'Bold Condensed 3';

foreach($array1 as $key => $value) {
    if (array_key_exists($key, $newarray)) {
        foreach($value as $subkey => $subvalue) {
            if (!array_key_exists($subkey, $newarray[$key])) {
                $newarray[$key][$subkey] = $subvalue;
            } elseif (array_key_exists($subkey, $newarray[$key]) and $subvalue != $newarray[$key][$subkey]) {
                $newkey = count($newarray[$key]);
                $newarray[$key][$newkey] = $subvalue;
            }
        }
    } else {
        $newarray[$key] = $value;
    }
}

//-------------
$array2 = array();
$array2[77][0] = 'Bold Condensed';
$array2[136][0] = 'Regular';

foreach($array2 as $key => $value) {
    if (array_key_exists($key, $newarray)) {
        foreach($value as $subkey => $subvalue) {
            if (!array_key_exists($subkey, $newarray[$key])) {
                $newarray[$key][$subkey] = $subvalue;
            } elseif (array_key_exists($subkey, $newarray[$key]) and $subvalue != $newarray[$key][$subkey]) {
                $newkey = count($newarray[$key]);
                $newarray[$key][$newkey] = $subvalue;
            }
        }
    } else {
        $newarray[$key] = $value;
    }
}

//-------------
$array3 = array();
$array3[77][0] = 'Bold Condensed (1, 2, 3)';
$array3[168][0] = 'Regular';
$array3[168][1] = 'Bold';

foreach($array3 as $key => $value) {
    if (array_key_exists($key, $newarray)) {
        foreach($value as $subkey => $subvalue) {
            if (!array_key_exists($subkey, $newarray[$key])) {
                $newarray[$key][$subkey] = $subvalue;
            } elseif (array_key_exists($subkey, $newarray[$key]) and $subvalue != $newarray[$key][$subkey]) {
                $newkey = count($newarray[$key]);
                $newarray[$key][$newkey] = $subvalue;
            }
        }
    } else {
        $newarray[$key] = $value;
    }
}

//Final result
print('<pre>'.print_r($newarray, true).'</pre>');

array_merge_recursive не требуется, поскольку для каждого идентификатора существует только 1 уровень, и ваш array_key_exists всегда будет истинным, поскольку вы получаете один и тот же ключ из foreach и проверяете один и тот же массив.


Вы можете сразу получить значения на основе id (в вашем случае это 77 и т. д.) и продолжать объединять значения. Позже вы сможете array_unique использовать их только один раз для повышения эффективности и получать только уникальные значения для каждого идентификатора.

<?php

$result = [];

foreach($d as $subs){
    foreach($subs as $id => $values){
        $result[ $id ] = array_merge($result[ $id ] ?? [], $values);
    }
}

$result = array_map(fn($v) => array_unique($v), $result);

print_r($result);

Живая демо

$result = array_map('array_unique', $result);
mickmackusa 25.09.2023 03:16
foreach ($arrays as $array) {
  foreach ($array as $key => $values) {
    $result[$key] = array_unique(array_merge($result[$key] ?? [], ...[ $values ]));
  }
}

Ответы, содержащие только код, упускают возможность обучать и расширять возможности тысяч будущих исследователей.

mickmackusa 25.09.2023 02:13

вот код

  <?php
    
    
    // Given arrays
    $array1 = [
        77 => ['Bold Condensed', 'Bold Condensed 2', 'Bold Condensed 3'],
    ];
    
    $array2 = [
        77 => ['Bold Condensed'],
        136 => ['Regular'],
    ];
    
    $array3 = [
        77 => ['Bold Condensed (1, 2, 3)'],
        168 => ['Regular', 'Bold'],
    ];
    
    // Function to merge arrays
    function mergeArrays(...$arrays)
    {
        $result = [];
    
        foreach ($arrays as $array) {
            foreach ($array as $key => $values) {
                if (!isset($result[$key])) {
                    $result[$key] = $values;
                } else {
                    // Merge values, removing duplicates
                    $result[$key] = array_values(array_unique(array_merge($result[$key], $values)));
                }
            }
        }
    
        return $result;
    }
    
    // Merge the arrays
    $mergedArray = mergeArrays($array1, $array2, $array3);
    
    // Output the merged array
    print_r($mergedArray);
    
    ?>

Функция mergeArrays принимает несколько массивов в качестве аргументов и объединяет их в один массив результатов. Он перебирает каждый массив, объединяя значения для каждого ключа и удаляя дубликаты.

Чтобы избежать более дорогостоящих вызовов array_merge() и array_unique() на каждой итерации вложенного цикла, поддерживайте временный массив поиска и помещайте в массив результатов только уникальные значения. Другими словами, не создавайте беспорядок в коде, чтобы потом его можно было навести порядок.

Код: (Демо)

$result = [];
foreach ($arrays as $set) {
    foreach ($set as $id => $row) {
        foreach ($row as $value) {
            if (!isset($lookup[$id][$value])) {
                $lookup[$id][$value] = $value;
                $result[$id][] = $value;
            }
        }
    }
}
var_export($result);

Выход:

array (
  77 => 
  array (
    0 => 'Bold Condensed',
    1 => 'Bold Condensed 2',
    2 => 'Bold Condensed 3',
    3 => 'Bold Condensed (1, 2, 3)',
  ),
  136 => 
  array (
    0 => 'Regular',
  ),
  168 => 
  array (
    0 => 'Regular',
    1 => 'Bold',
  ),
)

Другие вопросы по теме