How can I merge PHP arrays? - php

I have two arrays of animals (for example).
$array = array(
array(
'id' => 1,
'name' => 'Cat',
),
array(
'id' => 2,
'name' => 'Mouse',
)
);
$array2 = array(
array(
'id' => 2,
'age' => 321,
),
array(
'id' => 1,
'age' => 123,
)
);
How can I merge the two arrays into one by the ID?

#Andy
http://se.php.net/array_merge
That was my first thought but it doesn't quite work - however array_merge_recursive might work - too lazy to check right now.

This does what Erik suggested (id no. as array key) and merges vlaues in $array2 to $results.
$results = array();
foreach($array as $subarray)
{
$results[$subarray['id']] = array('name' => $subarray['name']);
}
foreach($array2 as $subarray)
{
if(array_key_exists($subarray['id'], $results))
{
// Loop through $subarray would go here if you have extra
$results[$subarray['id']]['age'] = $subarray['age'];
}
}

First off, why don't you use the ID as the index (or key, in the mapping-style array that php arrays are imo)?
$array = array(
1 => array(
'name' => 'Cat',
),
2 => array(
'name' => 'Mouse',
)
);
after that you'll have to foreach through one array, performing array_merge on the items of the other:
foreach($array2 as $key=>$value) {
if(!is_array($array[$key])) $array[$key] = $value;
else $array[$key] = array_merge($array[key], $value);
}
Something like that at least. Perhaps there's a better solution?

<?php
$a = array('a' => '1', 'b' => array('t' => '4', 'g' => array('e' => '8')));
$b = array('c' => '3', 'b' => array('0' => '4', 'g' => array('h' => '5', 'v' => '9')));
$c = array_merge_recursive($a, $b);
print_r($c);
?>
array_merge_recursive — Merge two or more arrays recursively
outputs:
Array
(
[a] => 1
[b] => Array
(
[t] => 4
[g] => Array
(
[e] => 8
[h] => 5
[v] => 9
)
[0] => 4
)
[c] => 3
)

#Andy
I've already looked at that and didn't see how it can help merge multidimensional arrays. Maybe you could give an example.
#kevin
That is probably what I will need to do as I think the code below will be very slow.
The actual code is a bit different because I'm using ADOdb (and ODBC for the other query) but I'll make it work and post my own answer.
This works, however I think it will be very slow as it goes through the second loop every time:
foreach($array as &$animal)
{
foreach($array2 as $animal2)
{
if($animal['id'] === $animal2['id'])
{
$animal = array_merge($animal, $animal2);
break;
}
}
}

foreach ($array as $a)
$new_array[$a['id']]['name'] = $a['name'];
foreach ($array2 as $a)
$new_array[$a['id']]['age'] = $a['age'];
and this is result:
[1] => Array
(
[name] => Cat
[age] => 123
)
[2] => Array
(
[name] => Mouse
[age] => 321
)

<?php
$array1 = array("color" => "red", 2, 4);
$array2 = array("a", "b", "color" => "green", "shape" => "trapezoid", 4);
$result = array_merge($array1, $array2);
print_r($result);
?>

With PHP 5.3 you can do this sort of merge with array_replace_recursive()
http://www.php.net/manual/en/function.array-replace-recursive.php
You're resultant array should look like:
Array (
[0] => Array
(
[id] => 2
[name] => Cat
[age] => 321
)
[1] => Array
(
[id] => 1
[name] => Mouse
[age] => 123
)
)
Which is what I think you wanted as a result.

I would rather prefer array_splice over array_merge because of its performance issues, my solution would be:
<?php
array_splice($array1,count($array1),0,$array2);
?>

$new = array();
foreach ($array as $arr) {
$match = false;
foreach ($array2 as $arr2) {
if ($arr['id'] == $arr2['id']) {
$match = true;
$new[] = array_merge($arr, $arr2);
break;
}
}
if ( !$match ) $new[] = $arr;
}

Related

Sum like values in Multi-Dimensional array php

I need to sum the values in element 1 of my array where the values in element 0 are duplicate.
Here's a small piece of my array
Array
(
[0] => 3
[1] => 1
)
Array
(
[0] => 3
[1] => 2
)
Array
(
[0] => 3
[1] => 128
)
Array
(
[0] => 39
[1] => 4
)
The results i'm expecting to see
Array
(
[0] => 3
[1] => 131
)
Array
(
[0] => 39
[1] => 4
)
I'm still really new to PHP so any help is greatly appreciated.
You can use a combination of array_intersect, array_column and array_sum to only iterate twice. (One for each unique column 0 value).
$col0 = array_column($arr, 0);
$col1 = array_column($arr, 1);
Foreach(array_unique($col0) as $val){
$res[] = [$val, array_sum(array_intersect_key($col1, array_intersect($col0,[$val])))];
}
Var_dump($res);
https://3v4l.org/gKb5b
The way I've done it is made sure all duplicates where put in the same array.
// Your data
$sample = [[3, 1],[3, 2],[3, 128],[39, 4]];
foreach($sample as $array){
$tmp[$array[0]][] = $array[1];
}
# Output: {"3":[1,2,128],"39":[4]}
Now sum the arrays, and put it back to the structure it originally was.
foreach($tmp as $k => $v){
$new[] = [$k, array_sum($v)];
}
# Output: [[3,131],[39,4]]
But many roads lead to Rome.
Try this code. It may help you.
$array = array(["0" => 3, "1" => 1] , ["0" => 3, "1" => 2], ["0" => 3, "1" => 128], ["0" => 39, "1" => 4]);
$finalArray = [];
foreach($array as $a) {
$finalArray[$a[0]][0] = $a[0];
$finalArray[$a[0]][1] = !isset($finalArray[$a[0]][1]) ? $a[1] : $finalArray[$a[0]][1] + $a[1];
}
echo '<pre>';
print_r($finalArray);
exit;
You could do something like this. I have separated into two foreach. Hope it helps.
<?php
$a = [[3,1],[3,2],[3,128],[39,4]];
$result=[];
$temp = [];
foreach($a as $line) {
$temp[$line[0]] += $line[1];
}
foreach($temp as $k => $value) {
$result[]=[$k ,$value];
}
$data =
[
[3,1],
[3,2],
[3,128],
[39,4]
];
foreach($data as $item)
$sums[$item[0]] = ($sums[$item[0]] ?? 0) + $item[1];
$result = array_map(null, array_keys($sums), $sums);
var_export($result);
Output:
array (
0 =>
array (
0 => 3,
1 => 131,
),
1 =>
array (
0 => 39,
1 => 4,
),
)
$arr = [ [ 3, 1],[ 3, 2 ],[ 3, 128], [ 39, 4]];
$sum = [];
foreach($arr as $value) {
$sum[$value[0]][] = $value[1];
}
foreach($sum as $key=>$value ) {
$result[] = [ $key, array_sum($value)];
}
Output:
Array
(
[0] => Array
(
[0] => 3
[1] => 131
)
[1] => Array
(
[0] => 39
[1] => 4
)
)

How to merge an array with child elements

I have an array with same customerid. I want to merge all same customerid arrays in to one with few amends to the array.
Array
(
[0] => Array
(
[customerid] => 13
[customer_fullname] => Chris
[profession_id] => 8
[profession_name] => Producer
)
[1] => Array
(
[customerid] => 1
[customer_fullname] => John
[profession_id] => 8
[profession_name] => Producer
)
[2] => Array
(
[customerid] => 13
[customer_fullname] => Chris
[profession_id] => 7
[profession_name] => Camera
)
)
So now I want a new array to be created like this:
Array(
[customerid] => 13
[customer_fullname] => Chris
[new_array] => array(
[0]=>[profession_id] => 8, [profession_name] => Producer,
[1]=>[profession_id] => 7, [profession_name] => Camera
)
)
Spent some time on it but wasn't able to get it right
There are better approaches if you're merging lots of records, but if you want a way to just merge two records as stated, I'd just do this:
$array1 = array(
'customerid' => 13
'customer_fullname' => 'John',
'profession_id' => 8,
'profession_name' => 'Producer'
);
$array2 = array(
'customerid' => 13
'customer_fullname' => 'John',
'profession_id' => 7,
'profession_name' => 'Director'
);
function merge_customers($customerA, $customerB)
{
$newCustomer = array();
if ($customerA['customerid'] == $customerB['customerid'])
{
$newCustomer['customerid'] = $customerA['customerid'];
$newCustomer['customer_fullname'] = $customerA['customer_fullname'];
$newCustomer['new_array'] = array(
array(
'profession_id' => $customerA['profession_id'],
'profession_name' => $customerA['profession_name']
),
array(
'profession_id' => $customerB['profession_id'],
'profession_name' => $customerB['profession_name']
)
);
return $newCustomer;
}
/* We can't merge these if they're different customers. */
return NULL;
}
The extended solution which is also well-suited for finding and "merging" multiple groups of entries which has same customerid. Used functions: array_filter, array_count_values, array_keys, array_walk, array_chunk and array_values:
// supposing $arr is your initial array
// finds which 'customerid' has multiple entries
$dupIds = array_filter(array_count_values(array_column($arr, "customerid")), function($v) {
return $v > 1;
});
$dupIds = array_keys($dupIds);
$result = [];
array_walk($arr, function($v) use(&$result, $dupIds) {
if (in_array($v['customerid'], $dupIds)) {
$parts = array_chunk($v, 2, true);
if (!isset($result[$v['customerid']])) {
$result[$v['customerid']] = $parts[0] + ['new_array' => [$parts[1]]];
} else {
$result[$v['customerid']]['new_array'][] = $parts[1];
}
}
});
print_r(array_values($result));
The output:
Array
(
[0] => Array
(
[customerid] => 13
[customer_fullname] => Chris
[new_array] => Array
(
[0] => Array
(
[profession_id] => 8
[profession_name] => Producer
)
[1] => Array
(
[profession_id] => 7
[profession_name] => Camera
)
)
)
)
Quick hack, maybe there is a nicer solution.
Note: The second "for each" loop is only needed if there is the possibility that the arrays don't have the same fields.
function merge($array1, $array2){
$result = array();
foreach($array1 as $key => $value){
if(isset($array2[$key]) && $array2[$key]!=$array1[$key]){
$result[$key][]=$value;
$result[$key][]=$array2[$key];
}else{
$result[$key]=$value;
}
}
foreach($array2 as $key => $value){
if(!isset($result[$key])){
$result[$key] = $value;
}
}
return $result;
}
print_r(merge($array1, $array2));

Reduce Multidimensional Array Into One Array

Simply to said I need help, how to make multidimension array into one array without change the key array?
From these :
Array
(
[0] => Array
(
[554] => a
)
[1] => Array
(
[561] => b
)
[2] => Array
(
[574] => c
)
)
Into these :
Array
(
[554] => a
[561] => b
[574] => c
)
I like to use array_walk_recursive for problems like this:
function flatten($array)
{
$temp=array();
array_walk_recursive($array, function($item, $key) use (&$temp) {
$temp[$key]=$item;
});
return $temp;
}
$a = array(
array(
564=>'a',
),
array(
561=>'b',
array(
562=>'d',
array(
563=>'e',
),
),
),
array(
574=>'c',
),
);
$b = flatten($a);
print_r($b);
This is my output:
Array
(
[564] => a
[561] => b
[562] => d
[563] => e
[574] => c
)
I'll just have to post this, since all the other current answers are so terrifically overcomplicated:
$result = array_reduce($array, function ($result, $array) { return $result + $array; }, array());
That's all that's needed.
i hope i can help you, first of all and do not take this wrong, you have got to investigate a little further, before asking for solutions, i strongly recommend you to go to www.php.net , http://php.net/manual/en/book.array.php and search for array documentation, enough said you are looking at ways to loop through array, actually you are looking for the "foreach" statement, here i have made a simple solution which you can convert into function later:
<?php
$original = array
(
0 => array(554 => 'a'),
1 => array(561 => 'b'),
2 => array(574 => 'c'),
);
/*$result = Array
(
[554] => a
[561] => b
[574] => c
);*/
$result = array();
foreach ($original as $sub_array) {
//this help us read first level array
foreach ($sub_array as $subArrayKey=>$subArray) {
// this help us read second level array
$result[$subArrayKey] = $subArray;
}
}
echo '<pre>';
print_r($result);
echo '</pre>';
?>
This should work for you:
$array = array(
array(554 => "a"),
array(561 => "b"),
array(574 => "c")
);
function getL2Keys($array) {
foreach($array as $sub)
$result[] = array_keys($sub);
return call_user_func_array('array_merge', array_values($result));
}
$array = array_combine(getL2Keys($array), call_user_func_array('array_merge', array_values($array)));
print_r($array);
Output:
Array
(
[554] => a
[561] => b
[574] => c
)

find duplicate value in multi-dimensional array

From a function I am given a multidimensional array like this:
array(
[0] => array(
[0] => 7,
[1] => 18
),
[1] => array(
[0] => 12,
[1] => 7
),
[2] => array(
[0] => 12,
[1] => 7,
[2] => 13
)
)
I need to find duplicate values in the 3 arrays within the main array. For example, if value 7 repeats in the 3 arrays, return 7.
<?php
$array = array(array(7,18), array(12,7), array(12, 7, 13));
$result = array();
$first = $array[0];
for($i=1; $i<count($array); $i++){
$result = array_intersect ($first, $array[$i]);
$first = $result;
}
print_r($result);//7
?>
use my custom function
function array_icount_values($arr,$lower=true) {
$arr2=array();
if(!is_array($arr['0'])){$arr=array($arr);}
foreach($arr as $k=> $v){
foreach($v as $v2){
if($lower==true) {$v2=strtolower($v2);}
if(!isset($arr2[$v2])){
$arr2[$v2]=1;
}else{
$arr2[$v2]++;
}
}
}
return $arr2;
}
$arr = array_icount_values($arry);
echo "<pre>";
print_r($arr);
exit;
OUPUT
Array
(
[7] => 3
[18] => 1
[12] => 2
[13] => 1
)
hope this will sure help you.
$input = array("a" => "green", "red", "b" => "green", "blue", "red");
$result = array_unique($input);
print_r($result);
use this code
$array = array(0 => 'blue', 1 => 'red', 2 => 'green', 3 => 'red');
$key = array_search('green', $array); // $key = 2;
You will need to loop through the first array, and for each value in it, see if it is in_array().
$findme = array();
foreach ($array[0] as $key => $value)
{
if (in_array ($value, $array[1]) && in_array ($value, $array[2]))
{
$findme[] = $value;
}
}
// $findme will be an array containing all values that are present in all three arrays (if any).

merge arrays without reindexing keys

I have two arrays that I want to merge recursively, so adding arrays is not an option. This is simple example without multilevels to demonstrate the problem:
$a1 = Array(
5 => 'pronoun'
)
$a2 = Array(
2 => 'verb',
3 => 'noun'
)
$r = array_merge_recursive($a1, $a2)
And I want to get that resulting array:
Array(
5 => 'pronoun'
2 => 'verb',
3 => 'noun'
)
My problem is that array_merge_recursive function reindixes keys, and I get the following:
Array(
0 => 'pronoun'
1 => 'verb',
2 => 'noun'
)
I understand that's happening because all my keys are numeric. So I tried to make them string when adding but it doesn't seem to be working properly:
$a1[(string)7] = 'some value';
The key - 7 - is still number, or at least that's how it is displayed in debugger - $a1[7] and not $a1['7']. Any advice?
EDIT:
Addition of arrays is not an option. Please see why. I have two multilevel arrays:
$a1 = array (
1 => array (
1 => "man1",
2 => "man"
),
2 => array (
1 => "run",
2 => "nice"
)
);
$a2 = array(
2 => array (
1 => "to observe",
2 => "to examine visually"),
3 => array(
1 => "look nice",
2 => "appear, seem to be"));
$r = $a1 + $a2;
What I expect is the following:
$r = Array(
...
2 => array(
1 => array("run", "to observe")
2 => array("nice", "to examine visually")
));
But instead the options for the key 2 from the second array is not added:
$r = Array(
...
2 => array(
1 => "run",
2 => "nice"
));
you can just use $a1+$a2 to get your result
$a1 = array(
5 => 'pronoun'
);
$a2 = array(
2 => 'verb',
3 => 'noun'
);
print_r($a1+$a2);
For recursive array
$a1 = array(
5 => 'pronoun'
);
$a2 = array(array('a', 'z'), array(2 => 'p', 'q'));
print_r($a1+$a2);
Result is
Array
(
[5] => pronoun
[0] => Array
(
[0] => a
[1] => z
)
[1] => Array
(
[2] => p
[3] => q
)
)
is this what you want to achieve?
This should apply to your particular problem:
function assoc_merge(array $a, array $b)
{
$r = array();
foreach ($a as $key => $val) {
if (array_key_exists($key, $b) && is_array($val) == is_array($b[$key])) {
if (is_array($val)) {
$r[$key] = assoc_merge($a[$key], $b[$key]); // merge array
} else {
$r[$key] = array($val, $b[$key]); // merge entry
}
} else {
$r[$key] = $val; // just copy
}
}
return $r + $b; // add whatever we missed
}
print_r(assoc_merge($a1, $a2));
You can always try the manual case.
function merge () { // takes any number of arguments
$arrays = func_get_args();
$result = array();
foreach ($arrays as $array)
foreach ($array as $key => $item)
if (is_array($item))
$result = merge($result, $item);
else
$result[$key] = $item;
return $result;
Sure, it's slow, but it will work.
$a1 = array(
5 => 'pronoun'
);
$a2 = array(
2 => 'verb',
3 => 'noun'
);
foreach($a2 as $key=>$value) {
$a1[$key] = $value;
}
print_r($a1);
<?php
$a = [ 5 => 'pronoun'];
$b = [ 2 => 'verb', 3 => 'noun'];
$m = array_merge(array_keys($a), array_keys($b));
$final = array_combine($m, array_merge_recursive($a, $b));
print_r($final);

Categories