Related
This question already has answers here:
Merge row data from multiple arrays
(6 answers)
Closed 4 months ago.
I'm currently stuck on how to merge multi query result into single result like;
multiple result:
$a1 = array(
["name" => "coca-cola"],
["name" => "sprite"],
["name" => "pepsi"]
);
$a2 = array(
["color" => "red"],
["color" => "green"],
["color" => "blue"]
);
$a3 = array(
["price" => 2],
["price" => 1],
["price" => 4]
);
expected output:
$res = array(
["name" => "coca-cola","color" => "red", "price" => 2],
["name" => "sprite","color" => "green", "price" => 1],
["name" => "pepsi","color" => "blue", "price" => 4]
);
Try this solution.
$a1 = array(
["name" => "coca-cola"],
["name" => "sprite"],
["name" => "pepsi"]
);
$a2 = array(
["color" => "red"],
["color" => "green"],
["color" => "blue"]
);
$a3 = array(
["price" => 2],
["price" => 1],
["price" => 4]
);
$res = array();
for($i=0; $i<count($a1); $i++){
$res[] = array_merge($a1[$i],$a2[$i],$a3[$i]);
}
Here we are assuming that all $a1, $a3, $a3 arrays have the same dimension.
One more solution:
$result = array_map(
function($name, $color, $price) {
return array_merge($name, $color, $price);
},
$a1, $a2, $a3
);
print_r($result);
share PHP code
Array
(
[0] => Array
(
[name] => coca-cola
[color] => red
[price] => 2
)
[1] => Array
(
[name] => sprite
[color] => green
[price] => 1
)
[2] => Array
(
[name] => pepsi
[color] => blue
[price] => 4
)
)
I searched a lot of SOF threads and no one seems to stick to my problem. What's kind of wired because this should be a well discussed question :)
Maybe I'm seeking for the wrong thing...
Scenario:
I have 2 arrays
$a = [
['id' => 5, 'name' => 'bruce'],
['id' => 7, 'name' => 'wayne']
];
// 2 elements
and
$b = [
['id' => 6, 'name' => 'chuck'],
['id' => 8, 'name' => 'norris'],
['id' => 7, 'name' => 'wayne'] //also exists in array $a
];
// 3 elements
My goal is
$c = [
['id' => 6, 'name' => 'chuck'],
['id' => 8, 'name' => 'norris'],
['id' => 7, 'name' => 'wayne'],
['id' => 5, 'name' => 'bruce']
];
// 4 elements (no duplicates)
I really don't care about the order inside the array(s) but I want to merge both into one, without having duplicates.
I tried array_merge and array_merge_recursive. No one works. Probably because the functions doesn't know the identifier which identifies each entry. Is there an easy solution or do I really have to create an own method/function for this?
Maybe there is a closure that I could use?
You can do this with very simple inbuilt function of PHP
$c = array_unique(array_merge($a,$b), SORT_REGULAR);
print_r( $c )
The output of the print_r is
Array
(
[0] => Array
(
[id] => 5
[name] => bruce
)
[1] => Array
(
[id] => 7
[name] => wayne
)
[2] => Array
(
[id] => 6
[name] => chuck
)
[3] => Array
(
[id] => 8
[name] => norris
)
)
$temp = array_merge($b, $a);
foreach ($temp as $v) {
$c[$v['id']] = $v;
}
If it finds the same id, the element will be overwritten in $c
Here's an approach at hashing each array with serialize after a key sort:
<?php
$a = [
['id' => 5, 'name' => 'bruce'],
['id' => 7, 'name' => 'wayne']
];
$b = [
['id' => 6, 'name' => 'chuck'],
['name' => 'wayne', 'id' => 7],
['id' => 8, 'name' => 'norris']
];
$merged = array_merge($a, $b);
foreach($merged as $k => $v) {
ksort($v);
$hashes[$k] = serialize($v);
}
$hashes = array_unique($hashes);
var_export(array_intersect_key($merged, $hashes));
Output:
array (
0 =>
array (
'id' => 5,
'name' => 'bruce',
),
1 =>
array (
'id' => 7,
'name' => 'wayne',
),
2 =>
array (
'id' => 6,
'name' => 'chuck',
),
4 =>
array (
'id' => 8,
'name' => 'norris',
),
)
If you index them on unique id then just add them. The result will be indexed on id which is convenient:
$result = array_column($a, null, 'id') + array_column($b, null, 'id');
I don't know how performant this is, but just using phps array-manipulation functions I get:
>>> array_values(array_merge(array_combine(array_column($a, 'name'), $a), array_combine(array_column($b, 'name'), $b)));
=> [
[
"id" => 5,
"name" => "bruce",
],
[
"id" => 7,
"name" => "wayne",
],
[
"id" => 6,
"name" => "chuck",
],
[
"id" => 8,
"name" => "norris",
],
]
This question already has answers here:
Merge arrays of associative arrays by shared column values [duplicate]
(3 answers)
Closed 5 months ago.
I have two arrays of arrays that have an id key, and I'd like to merge the data together based on that array's key and key value. The data would look something like:
$color = [
['id' => 1, 'color' => 'red'],
['id' => 2, 'color' => 'green'],
['id' => 3, 'color' => 'blue'],
];
$size = [
['id' => 1, 'size' => 'SM'],
['id' => 2, 'size' => 'XL'],
['id' => 3, 'size' => 'MD'],
['id' => 4, 'size' => 'LG'],
];
$combined = [
['id' => 1, 'color' => 'red', 'size' => 'SM'],
['id' => 2, 'color' => 'green', 'size' => 'XL'],
['id' => 3, 'color' => 'blue', 'size' => 'MD'],
['id' => 4, 'size' => 'LG'],
];
Is there a particularly efficient function or trick for handling something like this? Or should I just loop through the elements of one array and push the contents to the other?
I'm also using Laravel, and the data is a result of an eloquent query, so I can also utilize the collections if it would make the code cleaner.
Use array_replace_recursive function for easy and fast way
array_replace_recursive($color, $size)
Pure php solution is to use array_replace_recursive like this:
array_replace_recursive(
array_combine(array_column($color, "id"), $color),
array_combine(array_column($size, "id"), $size)
);
You should notice that array_replace_recursive merge arrays by keys.
So, if you get such data from database:
$color = [
['id' => 1, 'color' => 'red'],
['id' => 2, 'color' => 'red']
];
$size = [
['id' => 2, 'size' => 'SM']
];
array_replace_recursive will return corrupted merge:
$combined = [
['id' => 2, 'color' => 'red', 'size' => 'SM'],
['id' => 2, 'color' => 'red']
];
The solution is to combine array_replace_recursive with array_column and array_combine for merging arrays by their's id field:
array_replace_recursive(
array_combine(array_column($color, "id"), $color),
array_combine(array_column($size, "id"), $size)
);
array_combine(array_column($color, "id"), $color) creates associative array with id as keys.
So, in your case it will return:
$combined = [
1 => ['id' => 1, 'color' => 'red', 'size' => 'SM'],
2 => ['id' => 2, 'color' => 'green', 'size' => 'XL'],
3 => ['id' => 3, 'color' => 'blue', 'size' => 'MD'],
4 => ['id' => 4, 'size' => 'LG'],
];
You can use array_replace_recursive to merge the arrays in your particular situation.
$color = array(
array('id' => 1, 'color' => 'red'),
array('id' => 2, 'color' => 'green'),
array('id' => 3, 'color' => 'blue'),
);
$size = array(
array('id' => 1, 'size' => 'SM'),
array('id' => 2, 'size' => 'XL'),
array('id' => 3, 'size' => 'MD'),
array('id' => 4, 'size' => 'LG'),
);
$merged = array_replace_recursive($color, $size);
Output:
array(4) {
[0]=>
array(3) {
["id"]=>
int(1)
["color"]=>
string(3) "red"
["size"]=>
string(2) "SM"
}
[1]=>
array(3) {
["id"]=>
int(2)
["color"]=>
string(5) "green"
["size"]=>
string(2) "XL"
}
[2]=>
array(3) {
["id"]=>
int(3)
["color"]=>
string(4) "blue"
["size"]=>
string(2) "MD"
}
[3]=>
array(2) {
["id"]=>
int(4)
["size"]=>
string(2) "LG"
}
}
Note: I used the traditional array layout because my PHP version won't support the new one yet :)
Second option
You can also use array_map. This will let you add as much arrays as you want with a little tweaking.
$merged = array_map(function ($c, $s) {
return array_merge($c, $s);
}, $color, $size);
var_dump($merged); // See output above
I'd suggest using laravel's collections, since this question has the laravel tag.
$color = collect(
['id' => 1, 'color' => 'red'],
['id' => 2, 'color' => 'green'],
['id' => 3, 'color' => 'blue']
);
$size = collect(
['id' => 1, 'size' => 'SM'],
['id' => 2, 'size' => 'XL'],
['id' => 3, 'size' => 'MD'],
['id' => 4, 'size' => 'LG']
);
$combined = $color->merge($size);
Folllow this:
array_replace_recursive() is recursive : it will recurse into arrays and apply the same process to the inner value.
$combined = array_replace_recursive($color, $size);
then you can print to see the result as bellow:
print_r($combined);
Simple nested loop would solve the purpose.
foreach($size as $key => $value1) {
foreach($color as $value2) {
if($value1['id'] === $value2['id']){
$size[$key]['color'] = $value2['color'];
}
}
}
echo '<pre>';
print_r($size);
Output:
Array
(
[0] => Array
(
[id] => 1
[size] => SM
[title] => red
)
[1] => Array
(
[id] => 2
[size] => XL
[title] => green
)
[2] => Array
(
[id] => 3
[size] => MD
[title] => blue
)
[3] => Array
(
[id] => 4
[size] => LG
)
)
You need to traverse all elements from both arrays one by one and merge any duplicate elements. To do this you need to perform these steps.
Glue both arrays together.
$arr = [
['id' => 1, 'color' => 'red'],
['id' => 2, 'color' => 'green'],
['id' => 3, 'color' => 'blue'],
['id' => 1, 'size' => 'SM'],
['id' => 2, 'size' => 'XL'],
['id' => 4, 'size' => 'LG'],
['id' => 3, 'size' => 'MD'],
];
Loop the combined array copying the items into a new array.
If the ID has been seen before don't append the row, but merge it with an existing one.
You can achieve all of this with a single foreach loop and array_merge. There is no need for recursive functions or nested loops.
// Loops on merged arrays and copied elements into a new array
foreach(array_merge($color, $size) as $el){
// If the element with this id is already in new array then add the elements together
$merged[$el['id']] = ($merged[$el['id']] ?? []) + $el;
}
The only downside is that you lose the original indexes, but it looks from your question that this was not important to you. If you want, you can reindex the array with
$merged = array_values($merged);
Live Demo
Try:
$out = array();
foreach ($size as $key => $value){
if(!isset($color[$key])) { $color[$key] = array(); }
$out[] = array_merge((array)$value,(array)$color[$key]);
}
Output:
Array
(
[0] => Array
(
[id] => 1
[size] => SM
[color] => red
)
[1] => Array
(
[id] => 2
[size] => XL
[color] => green
)
[2] => Array
(
[id] => 3
[size] => MD
[color] => blue
)
[3] => Array
(
[id] => 4
[size] => LG
)
)
Better way using loop. First calculate the max array the by count this number run a loop. It will work.
I have this array. How do I remove all those elements which are present in another array i.e. $remove and re-index the final array starting from 1 not 0?
$info = array(
'1' => array('name' => 'abc', 'marks' => '56'),
'2' => array('name' => 'def', 'marks' => '85'),
'3' => array('name' => 'ghi', 'marks' => '99'),
'4' => array('name' => 'jkl', 'marks' => '73'),
'5' => array('name' => 'mno', 'marks' => '59')
);
$remove = array(1,3);
Desired Output:
$info = array(
'1' => array('name' => 'def', 'marks' => '85'),
'2' => array('name' => 'jkl', 'marks' => '73'),
'3' => array('name' => 'mno', 'marks' => '59')
);
So far I've tried these two methods. Nothing worked for me.
if (($key = array_search(remove[0], $info))) {
unset($info[$key]);
$info = array_values($info);
}
And
$result = array_diff($info, $remove);
Something like this will work:
$result = array_diff_key( $info, array_flip( $remove));
This array_flip()s your $remove array so the keys become the values and the values becomes the keys. Then, we do a difference against the keys with array_diff_key() of both arrays, to get this result:
Array
(
[2] => Array
(
[name] => def
[marks] => 85
)
[4] => Array
(
[name] => jkl
[marks] => 73
)
[5] => Array
(
[name] => mno
[marks] => 59
)
)
Finally, to yield your exact output, you can reindex your array by passing it through array_values(), but this will yield sequential indexes starting at zero, not one:
$result = array_values( array_diff_key( $info, array_flip( $remove)));
If you really need indexes to start at one, you will need a combination of array_combine() and range():
$result = array_diff_key( $info, array_flip( $remove));
$result = array_combine( range( 1, count( $result)), $result);
What about using array_diff function?
Example
$array1 = array("a" => "green", "red", "blue", "red");
$array2 = array("b" => "green", "yellow", "red");
$result = array_diff($array1, $array2);
print_r($result);
this will output
Array
(
[1] => blue
)
Was wondering how to add the values of one array into another to save me typing the values of one array over and over:
$array_main = array(
'[1]' => '1',
'[2]' => '2',
'[3]' => '3',
'[4]' => '4'
);
$array_1 = array( $array_main, '[5]' => '5' );
This deduces:
$array_1 = array(
array(
'[1]' => '1',
'[2]' => '2',
'[3]' => '3',
'[4]' => '4'
),
'[5]' => '5'
);
But I wanted:
$array_1 = array(
'[1]' => '1',
'[2]' => '2',
'[3]' => '3',
'[4]' => '4',
'[5]' => '5'
);
So is there anything that can turn an array into a string? I've tried implode and array_shift but I need the whole array() not just the values..
<?php
$array1 = array("color" => "red", 2, 4);
$array2 = array("a", "b", "color" => "green", "shape" => "trapezoid", 4);
$result = array_merge($array1, $array2);
print_r($result);
?>
The above example will output:
Array
(
[color] => green
[0] => 2
[1] => 4
[2] => a
[3] => b
[shape] => trapezoid
[4] => 4
)
http://php.net/manual/en/function.array-merge.php
Fastest way is simply use single array like following,
$array_main = array(
'[1]' => '1',
'[2]' => '2',
'[3]' => '3',
'[4]' => '4'
);
$array1 = $array_main;
$array1['[5]'] = '5';
Though if specific requirement for new array use array_merge,
$array1 = array_merge($array_main,array('[5]' => '5'));
You can use merge array (don't just want to add an extra value) to merge two arrays:
<?php
$array1 = array("0" => "0", "1" => "1");
$array2 = array("a" => "a", "b" => "b");
print_r( array_merge($array1, $array2 );
?>
Prints:
Array
(
[0] => 0
[1] => 1
[a] => a
[b] => b
)
Use array_merge()
$array_1 = array_merge($array_main, array('[5]' => '5'));