Как объединить два многомерных массива по значению ключа в php? - PullRequest
1 голос
/ 20 мая 2019

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

$arr1 = [
    ['month' => 1], 
    ['month' => 2], 
    ['month' => 3], 
    ['month' => 4]
];

$arr2 = [
    ['month' => 3, 'info' => 'Alpha'], 
    ['month' => 4, 'info' => 'Beta']
];

Я пытался array_merge & array_merge_recursive оба не объединяют массивы, как ожидалось.

Ожидаемое слияние:

$arr3 = [
    ['month' => 1], 
    ['month' => 2], 
    ['month' => 3, 'info' => 'Alpha'], 
    ['month' => 4, 'info' => 'Beta']
];

Фактически с array_merge_recursive является:

$arr3 = array_merge_recursive($arr2, $arr1);

$arr3 = [
    ['month' => 3, 'info' => 'Alpha'], 
    ['month' => 4, 'info' => 'Beta']
    ['month' => 1], 
    ['month' => 2], 
    ['month' => 3], 
    ['month' => 4]
];

Ответы [ 3 ]

3 голосов
/ 20 мая 2019

Если массивы ассоциативны по месяцу, вы можете использовать array_replace.
Сначала сделайте массивы ассоциативными с array_column, затем замените $ arr1 значениями $ arr2.

$arr1 = [
    ['month' => 1], 
    ['month' => 2], 
    ['month' => 3], 
    ['month' => 4]
];

$arr2 = [
    ['month' => 3, 'info' => 'Alpha'], 
    ['month' => 4, 'info' => 'Beta'],
    ['month' => 1, 'info' => 'Gamma'],
];


$arr1 = array_column($arr1, null, 'month');
$arr2 = array_column($arr2, null, 'month');

$result = array_replace($arr1, $arr2);
var_dump($result);

Возвращает:

array(4) {
  [1]=>
  array(2) {
    ["month"]=>
    int(1)
    ["info"]=>
    string(5) "Gamma"
  }
  [2]=>
  array(1) {
    ["month"]=>
    int(2)
  }
  [3]=>
  array(2) {
    ["month"]=>
    int(3)
    ["info"]=>
    string(5) "Alpha"
  }
  [4]=>
  array(2) {
    ["month"]=>
    int(4)
    ["info"]=>
    string(4) "Beta"
  }
}

https://3v4l.org/tpshB

Если у вас более старая версия PHP, в которой нет array_column, вы можете использовать этот устаревший код из руководства

if (!function_exists('array_column')) {
    function array_column($array, $columnKey, $indexKey = null)
    {
        $result = array();
        foreach ($array as $subArray) {
            if (is_null($indexKey) && array_key_exists($columnKey, $subArray)) {
                $result[] = is_object($subArray)?$subArray->$columnKey: $subArray[$columnKey];
            } elseif (array_key_exists($indexKey, $subArray)) {
                if (is_null($columnKey)) {
                    $index = is_object($subArray)?$subArray->$indexKey: $subArray[$indexKey];
                    $result[$index] = $subArray;
                } elseif (array_key_exists($columnKey, $subArray)) {
                    $index = is_object($subArray)?$subArray->$indexKey: $subArray[$indexKey];
                    $result[$index] = is_object($subArray)?$subArray->$columnKey: $subArray[$columnKey];
                }
            }
        }
        return $result;
    }
}
0 голосов
/ 20 мая 2019

В этом случае я хожу по массивам и создаю желаемый результат.

$output = [];
$allMerged = array_merge($arr1, $arr2);
array_walk($allMerged, 
  function($item, $key) use (&$output) {
    print_r($item);
    if ( array_key_exists($item['month'], $output) ) {
        if ( isset($item['info']) ) {
            $output[$item['month']]['info'] = $item['info'];
        } else {
            $output[$item['month']] = $item;
        }
    } else {
        $output[$item['month']] = $item;
    }
});
print_r($output);
0 голосов
/ 20 мая 2019

U можете попробовать следующий код

$newArr = [];
foreach($arr1 as $row) {
    $newArr[$row['month']] = $row;
}
foreach($arr2 as $arr) {
    if(array_key_exists($arr['month'], $newArr)) {
        $newArr[$arr['month']]['info'] = $arr['info'];
    }
} 

print_r($newArr);
...