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


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.