Как объединить значения подмассива и удалить дубликаты?

$arr[] = array('A','B');
$arr[] = array('C','B');
...

Мне нужно получить объединенный результат всех подмассивов $arr .

И для дублированных записей следует получить только одну.


person user198729    schedule 26.01.2010    source источник


Ответы (7)


Если вы действительно не хотите зацикливаться, попробуйте следующее:

$arr[] = array('A','B');
$arr[] = array('C','B');
$arr[] = array('C','D');
$arr[] = array('F','A');
$merged = array_unique(call_user_func_array('array_merge', $arr));
person bish    schedule 26.01.2010
comment
Я думаю, что нет необходимости в array_unique, так как array_merge перезапишет повторяющиеся ключи, если они будут обнаружены. Кто-нибудь может мне ответить? - person Ankit; 02.04.2016
comment
без 'array_merge' возникает следующая ошибка ErrorException: call_user_func_array() ожидает ровно 2 параметра @Ankit - person LeRoy; 26.04.2016
comment
гений, один из редких случаев, когда мы действительно можем использовать call_user_func_array, и он идеально подходит для такого рода вещей. - person Robert Sinclair; 16.08.2017

ОК, через другой вопрос я узнал, что на самом деле возможно следующее (я безуспешно пытался, у меня была неправильная версия), если вы используете версия PHP >= 5.3.0:

$merged_array = array_reduce($arr, 'array_merge', array());

Если вам нужны только уникальные значения, вы можете применить array_unique:

$unique_merged_array = array_unique($merged_array);

Это работает, если у вас есть только плоские элементы в массивах (т.е. нет других массивов). Из документации:

Примечание. Обратите внимание, что array_unique() не предназначен для работы с многомерными массивами.

Если у вас есть массивы в ваших массивах, вам нужно проверить вручную, например. с array_walk:

$unique_values = array();

function unique_value($value, &$target_array) {
    if(!in_array($value, $target_array, true))
        $target_array[] = $value;
}

array_walk($merged_values, 'unique_value', $unique_values);

Я думаю, можно предположить, что внутренние циклы (то есть то, что делает array_walk) по крайней мере не медленнее, чем явные циклы.

person Felix Kling    schedule 26.01.2010
comment
Я не думаю, что $merged_array = array_merge($arr); фактически разобьет подмассивы, о чем, я уверен, просил ОП. - person sprugman; 26.01.2010
comment
Стоит отметить, что array_merge должен быть в кавычках, например. 'массив_слияние' - person Matthew Riches; 03.01.2014

array_unique(array_merge($arr[0], $arr[1]));

или для неограниченного случая, я думаю, это должно работать:

$result_arr = array();
foreach ($arr as $sub_arr) $result_arr = array_merge($result_arr, $sub_arr);
$result_arr = array_unique($result_arr);
person sprugman    schedule 26.01.2010
comment
Он может иметь более 2 подмассивов. - person user198729; 26.01.2010
comment
Количество подмассивов является динамическим. - person user198729; 26.01.2010
comment
Несмотря на то, что автор приводит в качестве примера только $arr 0 + 1, я думаю, что им нужно решение для размещения всех дочерних элементов $arr. - person Ben Everard; 26.01.2010
comment
Есть ли способ сделать это, кроме цикла? - person user198729; 26.01.2010
comment
Почему? что не так с циклом? Я полагаю, вы могли бы использовать какую-то функцию сопоставления. Посмотрите раздел массива документов php для других идей. php.net/manual/en/ref.array.php - person sprugman; 26.01.2010
comment
Если количество массивов является динамическим, я думаю, что циклы могут быть лучшим выбором. Почему бы вам не зациклиться? - person Anthony Forloney; 26.01.2010
comment
Есть ли функция массива, которая может справиться с этой проблемой? - person user198729; 26.01.2010
comment
array_walk() возможен, но это больше накладных расходов - person sprugman; 26.01.2010
comment
Это все равно неправильно, должно быть $result_arr = array_merge($result_arr, $sub_arr); - person Felix Kling; 27.01.2010

$merged_array = array_reduce($serp_res, 'array_merge', array()); с добавленными квотами у меня сработало «array_merge».

person Goce Ribeski    schedule 31.01.2012

Этот ответ основан на сообщении Феликса Клинга. Это более точная версия с исправлением подэлементов "не массив".

$res = array_reduce($res, function(&$res, $v) {
                            return array_merge($res, (array) $v);
                        }, array());
person 23W    schedule 27.11.2014
comment
Отличное решение и используйте array_filter(), чтобы избавиться от пустых элементов массива, вызванных пустыми значениями массива или строками, добавленными ранее. Вот окончательная версия: $res = array_filter(array_reduce($res, function(&$res, $v) {return array_merge($res, (array) $v);}, array())); - person Tarik; 24.10.2016

Для PHP 5.6 с оператором splat:

array_unique(array_merge(...$arr));
person Gannet    schedule 12.09.2017

Простой способ справиться с этим в версии PHP >= 5.6 — использовать оператор splat, также называемый распаковкой аргумента. .

$arr = array_unique(array_merge(...$arr));
person Mat Lipe    schedule 22.11.2017