2

I have two arrays as shown below. I need to merge the content of the arrays so that I can get the structure as shown in the third array at last. I have checked array_merge but can't figure out the way this is possible. Any help appreciated. Thanks.

[
    ['gross_value' => '100', 'quantity' => '1'],
    ['gross_value' => '200', 'quantity' => '1']
]

and

[
    ['item_title_id' => '1', 'order_id' => '4'],
    ['item_title_id' => '2', 'order_id' => '4']
];

I should get a merged array like this:

[
    [
        'gross_value' => '100',
        'quantity' => '1',
        'item_title_id' => '1',
        'order_id' => 4
    ],
    [
        'gross_value' => '200',
        'quantity' => '1',
        'item_title_id' => '2',
        'order_id' => 4
    ]
]
mickmackusa
  • 43,625
  • 12
  • 83
  • 136
Abhishek
  • 1,459
  • 3
  • 19
  • 35

6 Answers6

1

how about:

$arr1 = array(
    0 => array(
        'gross_value' => '100',
        'quantity' => '1'
    ),
    1 => array(
        'gross_value' => '200',
        'quantity' => '1'
    )
);
$arr2 = array(
    0 => array(
        'item_title_id' => '1',
        'order_id' => '4'
    ),
    1 => array(
        'item_title_id' => '2',
        'order_id' => '4'
    )
);
$arr = array();
foreach($arr1 as $k => $v) {
    array_push($arr, array_merge($v, $arr2[$k]));
}
print_r($arr);

output:

Array
(
    [0] => Array
        (
            [gross_value] => 100
            [quantity] => 1
            [item_title_id] => 1
            [order_id] => 4
        )

    [1] => Array
        (
            [gross_value] => 200
            [quantity] => 1
            [item_title_id] => 2
            [order_id] => 4
        )

)

Have a look at array_merge

Toto
  • 89,455
  • 62
  • 89
  • 125
1

Use array_merge_recursive :

Convert all numeric key to strings, (make is associative array)

$result = array_merge_recursive($ar1, $ar2);
print_r($result);

See live demo here

Roopendra
  • 7,674
  • 16
  • 65
  • 92
0

I would probably iterate over the arrays and merge them manually.

$result = array();
foreach ( $array1 as $key => $item )
{
    $result[$key] = array_merge($array1[$key], $array2[$key]);
}

You will have an issue if the top-level arrays don't have strictly matching keys though.

Maxim Kumpan
  • 2,545
  • 2
  • 19
  • 23
0

If you have $array1 and $array2, try this:

foreach($array1 as $key1=>$innerArray){
    $array1[$key1]['item_title_id'] = $array2[$key1]['item_title_id'];
    $array1[$key1]['order_id'] = $array2[$key1]['order_id'];
}
ljubiccica
  • 480
  • 3
  • 17
0

The problem with things like merge recursive is that they don't know when to stop.

In some scenarios you want to stop traversing down an array and simply take a given value if it exists.

For instance if you have to override a nested config array you might not want the default keys to stick around at a a specific level.

here is my solution:

public static function merge_lvl2(){
    $args = func_get_args();
    return static::merge($args, 2);
}

public static function merge($args, $maxDepth = null, $depth = 1)
{
    $merge = [];
    foreach($args as $arg) {
        if (is_array($arg)) {
            if (is_array($merge)) {
                if ($maxDepth == $depth) {
                    $arg += $merge;
                    $merge = $arg;
                } else {
                    $merge = array_merge($merge, $arg);
                }
            } else {
                $merge = $arg;
            }
        }
    }
    if ($maxDepth !== $depth) {
        foreach($args as $a) {
            if (is_array($a)) {
                foreach($a as $k => $v) {
                    if (isset($merge[$k]) && is_array($merge[$k])) {
                        $merge[$k] = static::merge([$merge[$k], $v], $maxDepth, $depth + 1);
                    }
                }
            }
        }
    }
    return $merge;
}

You can pass as many arrays to merge as you want to.

$merged = ClassName::merge_lvl2([..array1..], [..array2..], [..array3..], etc...);

It will stop merging at level 2 and accept the last instance of the key as an override instead of a merge.

You can also call merge directly with an array of args and setting the max depth.

If no max depth is set it will traverse the entire array.

Dieter Gribnitz
  • 5,062
  • 2
  • 41
  • 38
0

The most modern, elegant, concise way to merge rows from two or more arrays (or the rows from a multidimensional array with 3 or more levels of depth) is to call array_merge() on each row (array_replace() can also be used). array_map() can call array_merge by its string name and the input data can be split into individual arguments with the "spread operator" (...) when needed.

Code for the OP's arrays: (Demo)

var_export(
    array_map('array_merge', $arr1, $arr2)
);

The above technique will return a newly indexed array (though you might not notice because the sample input arrays were indexed to begin with). If your input data has associative first-level keys, they will be ignored and destroyed by this technique. If you have non-numeric first-level keys and want to merge on those, then array_merge_recursive() is likely to be the ideal native function - Demo.

However, it must be said, that for the OP's sample data array_merge_recursive() IS NOT a correct technique.

My first snippet is conveniently extended if you have more than two arrays which need their rows to be merge based on their positions. (Demo)

var_export(
    array_map('array_merge', $arr1, $arr2, $arr3)
);

And as mentioned earlier, the spread operator can be used to unpack deeper arrays with the same result. Again, the number of subarrays containing rows can be dynamic. If your deep array only has one subarray containing rows, then the result will be a "flattening" effect where the top level is removed.

Code with new data structure: (Demo)

$masterArray = [
    [
        ['gross_value' => '100', 'quantity' => '5'],
        ['gross_value' => '200', 'quantity' => '6']
    ],
    [
        ['item_title_id' => '1', 'order_id' => '3'],
        ['item_title_id' => '2', 'order_id' => '4']
    ],
    [
        ['foo' => 'bar1'],
        ['foo' => 'bar2']
    ]
];

var_export(
    array_map('array_merge', ...$masterArray)
);

To be fair, array_replace_recursive() does provide the desired result using the OP's sample data, but I find the technique to be semantically misleading. (Demo)


All that said, you are not forced to use PHP's native array functions; you can use classic loops as well -- you will have several ways to "unite" the rows inside the loop. This approach is a little less D.R.Y. because you need to explicitly specific the separate arrays that you wish to synchronously iterate. Just make sure that you understand the nuanced differences in using array_merge(), array_replace(), and the union operator (+) with different qualities of data. Hint: associative, non-numeric keyed data in the respective rows will be affected when key collisions occur. Be careful to use a merging technique that will not overwrite the wrong data when rows share associative keys.

array_merge() to build a new array: (array_merge() Demo) (array_replace() Demo) (array union operator + Demo)

$result = [];
foreach ($arr1 as $i => $row) {
    $result[] = array_merge($row, $arr2[$i]);    
}
var_export($result);

Alternative, you can use the same general approach, but instead of populating a new $result array, you can merge data into the first array.

(array_merge() Demo) (array_replace() Demo) (array union assignment operator += Demo)

foreach ($arr1 as $i => &$row) {
    $row = array_merge($row, $arr2[$i]);    
}
var_export($arr1);

For the sake of completeness, if you have an indexed array of indexed arrays, then you might even use iterated calls of array_push() with the spread operator to achieve a similar functionality. This quite literally, indicatively appends the row data from subsequent arrays to the first array's rows.

Code: (Demo)

$arr1 = [
    ['A', 'B', 'C'],
    ['F', 'G']
];
$arr2 = [
    ['D', 'E'],
    ['H', 'I', 'J', 'L']
];

foreach ($arr1 as $i => &$row) {
    array_push($row, ...$arr2[$i]);
}
var_export($arr1);

Related non-duplicate content on Stack Overflow:

On the above pages, the rabbit hole goes further because I've linked other related pages to them. Keep researching until you find what you need.

If you are using Laravel, you might be interested in its combine() and collect() methods.

mickmackusa
  • 43,625
  • 12
  • 83
  • 136