Объедините два массива


88

У меня есть два таких массива:

array( 
'11' => '11',
'22' => '22',
'33' => '33',
'44' => '44'
);

array( 
'44' => '44',
'55' => '55',
'66' => '66',
'77' => '77'
);

Я хочу объединить эти два массива, чтобы они не содержали дубликатов, а также сохранили их исходные ключи. Например, вывод должен быть:

array( 
'11' => '11',
'22' => '22',
'33' => '33',
'44' => '44',
'55' => '55',
'66' => '66',
'77' => '77'
);

Я пробовал это, но он меняет их исходные ключи:

$output = array_unique( array_merge( $array1 , $array2 ) );

Любое решение?

Ответы:


161

Просто используйте:

$output = array_merge($array1, $array2);

Это должно решить эту проблему. Поскольку вы используете строковые ключи, если один ключ встречается более одного раза (как '44'в вашем примере), один ключ будет перезаписывать действующие ключи с тем же именем. Поскольку в вашем случае они оба имеют одинаковое значение, это не имеет значения, и он также удалит дубликаты.

Обновление: я только что понял, что PHP обрабатывает числовые строковые ключи как числа (целые числа) и поэтому будет вести себя так, что означает, что он также перенумеровывает ключи ...

Обходной путь - воссоздать ключи.

$output = array_combine($output, $output);

Обновление 2: я всегда забываю, что есть еще оператор (выделен жирным шрифтом, потому что это действительно то, что вы ищете!: D)

$output = $array1 + $array2;

Все это можно увидеть на: http://php.net/manual/en/function.array-merge.php


5
@KingCrunch - Несмотря на то, что числа указаны в кавычках, это не строковые ключи, поэтому индекс не будет сохранен. Пример: ideone.com/I2NFT
Брендан Буллен

1
Действительно ... Сначала я хотел поговорить об «ошибке», но потом заметил, что в руководстве говорится только о «цифровых клавишах», а не о «целочисленных клавишах». Немного сбивает с толку.
KingCrunch,

+1 про оператора забыл! Отлично (выделите эту часть жирным шрифтом!;))
Брендан Буллен

3
Так $array1 + $array2короткое и эффективное решение вместо array_merge() - array_combine()комбинации
Аван

2
ПРЕДУПРЕЖДЕНИЕ! для не связанных массивов или если массивы имеют общие ключи$a + $b != array_merge($a, $b)
jmarceli 08

33

Вы должны принять во внимание, что $array1 + $array2 != $array2 + $array1

$array1 = array(
'11' => 'x1',
'22' => 'x1' 
);  

$array2 = array(
'22' => 'x2',
'33' => 'x2' 
);

с $ array1 + $ array2

$array1 + $array2 = array(
'11' => 'x1',
'22' => 'x1',
'33' => 'x2'
);

и с $ array2 + $ array1

$array2 + $array1 = array(  
'11' => 'x1',  
'22' => 'x2',  
'33' => 'x2'  
);

25

Это работает:

$output = $array1 + $array2;

12
Я бы не рекомендовал это, потому что это поведение очень неинтуитивно, например[1,2,3] + [4,5,6] == [1,2,3]
jchook

@jchook Что вы посоветуете тогда?
Михас

Это то, что мне нужно, спасибо. Вот почему: http_build_query(array_merge($array1, $array2))у меня не сработало, тогда как сработало http_build_query($array1 + $array2).
BarryMode

4

Для этого вы можете перебрать один и добавить к другому:

<?php

$test1 = array( 
'11' => '11',
'22' => '22',
'33' => '33',
'44' => '44'
);

$test2 = array( 
'44' => '44',
'55' => '55',
'66' => '66',
'77' => '77'
);


function combineWithKeys($array1, $array2)
{
    foreach($array1 as $key=>$value) $array2[$key] = $value;
    asort($array2);
    return $array2;
} 

print_r(combineWithKeys($test1, $test2));

?>

ОБНОВЛЕНИЕ: KingCrunch предложил лучшее решение :print_r($array1+$array2);


2

Если вы используете PHP 7.4 или выше, вы можете использовать оператор распространения ...в качестве следующих примеров из документации PHP:

$arr1 = [1, 2, 3];
$arr2 = [...$arr1]; //[1, 2, 3]
$arr3 = [0, ...$arr1]; //[0, 1, 2, 3]
$arr4 = array(...$arr1, ...$arr2, 111); //[1, 2, 3, 1, 2, 3, 111]
$arr5 = [...$arr1, ...$arr1]; //[1, 2, 3, 1, 2, 3]

function getArr() {
  return ['a', 'b'];
}
$arr6 = [...getArr(), 'c']; //['a', 'b', 'c']

$arr7 = [...new ArrayIterator(['a', 'b', 'c'])]; //['a', 'b', 'c']

function arrGen() {
    for($i = 11; $i < 15; $i++) {
        yield $i;
    }
}
$arr8 = [...arrGen()]; //[11, 12, 13, 14]

Работает как в JavaScript ES6.

Подробнее см. Https://wiki.php.net/rfc/spread_operator_for_array .


Это не относится к вопросу. OP имеет строковые ключи для массива (это не работает с оператором распространения), а OP хочет сохранить ключи (оператор распространения выбрасывает ключи). Также OP не хочет дублировать.
martti,

О, я понимаю твои доводы. Это правда, и ты прав. Можете ли вы предоставить код, который поможет нам улучшить мой ответ для других? Буду признателен за ваше время! Большое спасибо за то, что указали на недостатки моего ответа.
Студент естественных наук

Я не думаю, что здесь можно использовать оператор спреда. Вместо этого используйте данный ответ$array1 + $array2
martti

Я не знал об этом! То есть, я не знал, что мы можем сделать $ouput = $array1 + $array2. Теперь я узнал кое-что новое! Спасибо!
Студент естественных наук

1

Это работает:

$a = array(1 => 1, 2 => 2, 3 => 3);
$b = array(4 => 4, 5 => 5, 6 => 6);
$c = $a + $b;
print_r($c);

1

Предупреждение! $ array1 + $ array2 перезаписывает ключи, поэтому мое решение (для многомерных массивов) - использовать array_unique ()

array_unique(array_merge($a, $b), SORT_REGULAR);

Уведомление:

5.2.10+ Изменено значение по умолчанию sort_flagsобратно на SORT_STRING.

5.2.9 По умолчанию SORT_REGULAR.

5.2.8- По умолчанию SORT_STRING

Он отлично работает . Надеюсь, это поможет.


1
array_merge()не сохраняет ключи. Созданный таким образом массив имеет индекс 0.
HPierce

@HPierce ну, в случае добавления многомерного массива некоторая информация будет потеряна при использовании +. Взгляните на: PHPFiddle , $ b [0] будет потеряно ...
Норман Эданс,

1

Новый способ сделать это с php7.4 - оператор распространения [...]

$parts = ['apple', 'pear'];
$fruits = ['banana', 'orange', ...$parts, 'watermelon'];
var_dump($fruits);

Оператор распространения должен иметь лучшую производительность, чем array_merge

Существенным преимуществом оператора Spread является то, что он поддерживает любые проходимые объекты, в то время как функция array_merge поддерживает только массивы.


Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.