Как объединить два массива, взяв только значения из второго массива, который имеет те же ключи, что и первый?

Я хочу объединить два массива друг с другом:

$filtered = array(1 => 'a', 3 => 'c');
$changed = array(2 => 'b*', 3 => 'c*');

Принимая во внимание, что слияние должно включать все элементы $filtered и все те элементы $changed, которые имеют соответствующий ключ в $filtered:

$merged = array(1 => 'a', 3 => 'c*');

array_merge($filtered, $changed) также добавит дополнительные ключи $changed в $filtered. Так что не очень подходит.

Я знаю, что могу использовать $keys = array_intersect_key($filtered, $changed) для получения ключей, которые существуют в обоих массивах, что уже составляет половину работы.

Однако мне интересно, есть ли какая-нибудь (собственная) функция, которая может уменьшить массив $changed в массив с $keys, указанным в array_intersect_key? Я знаю, что могу использовать array_filter с функцией обратного вызова и проверять $keys в ней, но, вероятно, есть какая-то другая чисто собственная функция для извлечения только тех элементов из массива, ключи которых могут быть указаны?

Я спрашиваю, потому что собственные функции часто намного быстрее, чем array_filter с обратным вызовом.


person hakre    schedule 03.07.2011    source источник


Ответы (3)


Это должно сработать, если я правильно понимаю вашу логику:

array_intersect_key($changed, $filtered) + $filtered

Реализация:

$filtered = array(1 => 'a', 3 => 'c');
$changed = array(2 => 'b*', 3 => 'c*');
$expected = array(1 => 'a', 3 => 'c*');    
$actual = array_key_merge_deceze($filtered, $changed);

var_dump($expected, $actual);

function array_key_merge_deceze($filtered, $changed) {
    $merged = array_intersect_key($changed, $filtered) + $filtered;
    ksort($merged);
    return $merged;
}

Выход:

Expected:
array(2) {
  [1]=>
  string(1) "a"
  [3]=>
  string(2) "c*"
}

Actual:
array(2) {
  [1]=>
  string(1) "a"
  [3]=>
  string(2) "c*"
}
person deceze♦    schedule 03.07.2011
comment
Союз против перекрестка. Но объединение также добавит ключи $filtered AFAIK. Я попробую. - person hakre; 03.07.2011
comment
Юп. Только что проверил, моя вина;). Он работает очень хорошо, меняется только порядок ключей, но это не проблема, поскольку у меня они есть в виде числового индекса, поэтому ksort выполняет свою работу. Идеально. Большое спасибо! - person hakre; 03.07.2011
comment
@deceze array_intersect_key($changed, $filtered) + $filtered Странно. Я такого раньше не видел. Понятия не имею, что здесь происходит, но это работает! Какая работа для + $filtered - person The Bndr; 11.04.2014
comment
@ array_intersect_key($changed, $filtered) принимает все значения из $changed, которые имеют ключ в $filtered, т.е. создает подмножество $filtered со значениями из $changed. + $filtered затем добавляет остальные значения из $filtered обратно в результат, т. Е. Заполняет подмножество, чтобы все ключи были в $filtered. - person deceze♦; 11.04.2014
comment
Вы можете разместить возврат $changed, когда $filtered пуст, в зависимости от вашего варианта использования. - person Goose; 17.05.2019

если вы хотите, чтобы второй массив ($ b) был шаблоном, который указывает, что если там есть только ключ, вы также можете попробовать это

$new_array =  array_intersect_key( $filtered, $changed ) + $changed;
person Lenin Zapata    schedule 22.11.2016

Если ваши ключи нечисловые (а у вас нет, поэтому это не решение вашего точного вопроса), вы можете использовать этот метод:

$filtered = array('a' => 'a', 'c' => 'c');
$changed = array('b' => 'b*', 'c' => 'c*');

$merged = array_slice(array_merge($filtered, $changed), 0, count($filtered));

Результат:

Array
(
    [a] => a
    [c] => c*
)

Это работает, потому что для нечисловых ключей array_merge перезаписывает значения для существующих ключей и добавляет ключи в $changed в конец нового массива. Таким образом, мы можем просто отбросить любые ключи из конца объединенного массива, превышающие количество в исходном массиве.

Поскольку это относится к тому же вопросу, но с разными типами ключей, я подумал, что предоставлю его.

Если вы используете это с числовыми клавишами, то результатом будет просто исходный массив ($filtered в данном случае) с переиндексированными клавишами (IE, как если бы вы использовали array_values).

person Dan    schedule 02.12.2020