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
)
)
Related
I have $tree like array which made by function from the $array I need a function to make it $tree to $array back
so I need a function to make it back.
lets call it $list this time.
I will share $tree , $array and the function in below
tree like array ;
Array
(
[0] => Array
(
[id] => 1
[name] => id1
[children] => Array
(
[0] => Array
(
[id] => 2
[parent_id] => 1
[name] => id2
[children] => Array
(
[0] => Array
(
[id] => 5
[parent_id] => 2
[name] => id5
)
)
)
[1] => Array
(
[id] => 3
[parent_id] => 1
[name] => id3
[children] => Array
(
[0] => Array
(
[id] => 6
[parent_id] => 3
[name] => id6
)
[1] => Array
(
[id] => 8
[parent_id] => 3
[name] => id8
)
)
)
)
)
[1] => Array
(
[id] => 4
[name] => id4
[children] => Array
(
[0] => Array
(
[id] => 9
[parent_id] => 4
[name] => id9
[children] => Array
(
[0] => Array
(
[id] => 10
[parent_id] => 9
[name] => id10
)
)
)
)
)
[2] => Array
(
[id] => 7
[name] => id7
[children] => Array
(
)
)
)
Which made by a function from this array
$array = [
['id'=> 1, 'parent_id' => 0, 'name' => 'id1'],
['id' => 2, 'parent_id' => 1, 'name'=> 'id2'],
['id' => 3, 'parent_id' => 1, 'name'=> 'id3'],
['id' => 4, 'parent_id' => 0, 'name'=> 'id4'],
['id' => 5,'parent_id' => 2, 'name'=> 'id5'],
['id' => 6, 'parent_id' => 3, 'name'=> 'id6'],
['id' => 7, 'parent_id' => 0, 'name'=> 'id7'],
['id' => 8, 'parent_id' => 3, 'name'=> 'id8'],
['id' => 9, 'parent_id' => 4, 'name'=> 'id9'],
['id' => 10, 'parent_id' => 9, 'name'=> 'id10'],
];
function(making $array in to $tree)
$tree = [];
function buildTree (array $infos, int $parent_Id = null): array
{
$branch = [];
foreach ($infos as $info)
if($info['parent_id'] === $parent_Id){
$children = buildTree($infos , $info['id']);
if ($children){
$info['children'] = $children;
}
$branch[] = $info;
}
return $branch;
}
foreach ($array as $info){
if($info['parent_id']=== 0){
$tree[] = [
'id' => $info['id'],
'name' => $info['name'],
'children' => buildTree($array , $info['id']),
];
}
}
print_r($tree);
any explanation would be appreciated.
Result of this code can be found here: http://sandbox.onlinephpfunctions.com/code/38a091db5ace63900fa0bf69ddde17412118513c
function flatMergeArray(array $array, int $parentId = 0, array &$result = []): array
{
$subResult = [];
foreach ($array as $key => $sub) {
$parentId = $array['parent_id'] ?? 0;
if (is_array($sub)) {
flatMergeArray($sub, $parentId, $result);
} else {
$subResult[$key] = $sub;
}
}
if (!empty($subResult)) {
if (!isset($subResult['parent_id'])) {
$subResult['parent_id'] = 0;
}
$result[] = $subResult;
}
return $result;
}
function flatTree(array $tree): array
{
$array = flatMergeArray($tree);
usort($array, static function (array $node1, array $node2) {
return ($node1['id'] < $node2['id']) ? -1 : 1;
});
return array_values($array);
}
$tree = [
[
"id" => 1,
"name" => "id1",
"children" => [
[
"id" => 2,
"parent_id" => 1,
"name" => "id2",
"children" => [
[
"id" => 5,
"parent_id" => 2,
"name" => "id5"
]
]
],
[
"id" => 3,
"parent_id" => 1,
"name" => "id3",
"children" => [
[
"id" => 6,
"parent_id" => 3,
"name" => "id6"
],
[
"id" => 8,
"parent_id" => 3,
"name" => "id8"
]
]
]
]
],
[
"id" => 4,
"name" => "id4",
"children" => [
[
"id" => 9,
"parent_id" => 4,
"name" => "id9",
"children" => [
[
"id" => 10,
"parent_id" => 9,
"name" => "id10"
]
]
]
]
],
[
"id" => 7,
"name" => "id7",
"children" => [
]
]
];
$array = flatTree($tree);
print_r($array);
Is it possible to sort (with php) an array like this by last name:
$array = array(
array("name" => "Mary Johnson","age" => 43),
array("name" => "Amanda Miller","age" => 23),
array("name" => "James Brown","age" => 47),
array("name" => "Patricia Williams","age" => 31),
array("name" => "Michael Davis","age" => 15),
array("name" => "Sarah Miller","age" => 35),
array("name" => "Patrick Miller","age" => 44)
);
<?php
// A function to sort by last name.
function lastNameSort($a, $b) {
$aLast = end(explode(' ', $a));
$bLast = end(explode(' ', $b));
return strcasecmp($aLast, $bLast);
}
// The array of data.
$array = array(
array("name" => "Mary Johnson","age" => 43),
array("name" => "Amanda Miller","age" => 23),
array("name" => "James Brown","age" => 47),
array("name" => "Patricia Williams","age" => 31),
array("name" => "Michael Davis","age" => 15),
array("name" => "Sarah Miller","age" => 35),
array("name" => "Patrick Miller","age" => 44)
);
// Perform the sort:
uasort($array, 'lastNameSort');
// Print the result:
print_r($array);
Its just an addressing issue. Amend you function as below, remember the $a and $b are arrays and not scalar variables.
$array = array(
array("name" => "Mary Johnson","age" => 43),
array("name" => "Amanda Miller","age" => 23),
array("name" => "James Brown","age" => 47),
array("name" => "Patricia Williams","age" => 31),
array("name" => "Michael Davis","age" => 15),
array("name" => "Sarah Miller","age" => 35),
array("name" => "Patrick Miller","age" => 44)
);
function sortByName($a, $b) {
$aLast = explode(' ', $a['name'])[1];
$bLast = explode(' ', $b['name'])[1];
return strcasecmp($aLast, $bLast);
}
#print_r($array);
usort($array, 'sortByName');
print_r($array);
RESULT
Array
(
[0] => Array ( [name] => James Brown [age] => 47 )
[1] => Array ( [name] => Michael Davis [age] => 15 )
[2] => Array ( [name] => Mary Johnson [age] => 43 )
[3] => Array ( [name] => Amanda Miller [age] => 23 )
[4] => Array ( [name] => Sarah Miller [age] => 35 )
[5] => Array ( [name] => Patrick Miller [age] => 44 )
[6] => Array ( [name] => Patricia Williams [age] => 31 )
)
And to get the Millers in the correct order by firstname as well as lastname, you code amend the sort function a little as below
function sortByName($a, $b) {
$t = explode(' ', $a['name']);
$aLast = $t[1] . $t[0];
$t = explode(' ', $b['name'])[1];
$bLast = $t[1] . $t[0];
return strcasecmp($aLast, $bLast);
}
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",
],
]
I currently have the following array:
Array
(
[0] => Array
(
[declaration_value] => 1
[date] => 2018-07-16
[client_id] => 3
[declaration_id] => 12
)
[1] => Array
(
[declaration_value] => 3
[date] => 2018-07-16
[client_id] => 3
[declaration_id] => 12
)
)
how can i make to get the following array result: (count declaration_value if the same date/client_id/declaration_id )
Array
(
[0] => Array
(
[declaration_value] => 4
[date] => 2018-07-16
[client_id] => 3
[declaration_id] => 12
)
)
$listdb = [
["declaration_value" => 1, "date" => "2018-07-16", "client_id" => 3, "declaration_id" => 12],
["declaration_value" => 2, "date" => "2018-07-16", "client_id" => 2, "declaration_id" => 12],
["declaration_value" => 2, "date" => "2018-07-16", "client_id" => 2, "declaration_id" => 12],
["declaration_value" => 8, "date" => "2018-07-17", "client_id" => 2, "declaration_id" => 12],
["declaration_value" => 3, "date" => "2018-07-16", "client_id" => 3, "declaration_id" => 12],
];
$sameKeys = ["date", "client_id", "declaration_id"];
$sumKeys = ["declaration_value"];
print_r(sum_my($listdb, $sameKeys, $sumKeys));
function sum_my(array $listdb = [], array $sameKeys = [], array $sumKeys = []): array {
$newdb = [];
if (empty($listdb) === true || empty($sameKeys) === true || empty($sumKeys) === true) {
return $newdb;
}
foreach ($listdb as $value) {
$ckKey = "";
foreach ($sameKeys as $sameKey) {
$ckKey .= $value[$sameKey];
}
if (isset($newdb[$ckKey])) {
foreach ($sumKeys as $sumKey) {
$newdb[$ckKey][$sumKey] += $value[$sumKey];
}
} else {
$newdb[$ckKey] = $value;
}
}
return $newdb;
}
Thank you for your tips, I solved it.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 months ago.
Improve this question
How to merge n number of array in php. I mean how can I do the job like :
array_merge(from : $result[0], to : $result[count($result)-1])
OR
array_merge_recursive(from: $result[0], to : $result[count($result) -1])
Where $result is an array with multiple arrays inside it like this :
$result = Array(
0 => array(),//associative array
1 => array(),//associative array
2 => array(),//associative array
3 => array()//associative array
)
My Result is :
$result = Array(
0 => Array(
"name" => "Name",
"events" => 1,
"types" => 2
),
1 => Array(
"name" => "Name",
"events" => 1,
"types" => 3
),
2 => Array(
"name" => "Name",
"events" => 1,
"types" => 4
),
3 => Array(
"name" => "Name",
"events" => 2,
"types" => 2
),
4 => Array(
"name" => "Name",
"events" => 3,
"types" => 2
)
)
And what I need is
$result = Array(
"name" => "name",
"events" => array(1,2,3),
"types" => array(2,3,4)
)
array_merge can take variable number of arguments, so with a little call_user_func_array trickery you can pass your $result array to it:
$merged = call_user_func_array('array_merge', $result);
This basically run like if you would have typed:
$merged = array_merge($result[0], $result[1], .... $result[n]);
Update:
Now with 5.6, we have the ... operator to unpack arrays to arguments, so you can:
$merged = array_merge(...$result);
And have the same results. *
* The same results as long you have integer keys in the unpacked array, otherwise you'll get an E_RECOVERABLE_ERROR : type 4096 -- Cannot unpack array with string keys error.
I really liked the answer from complex857 but it didn't work for me, because I had numeric keys in my arrays that I needed to preserve.
I used the + operator to preserve the keys (as suggested in PHP array_merge with numerical keys) and used array_reduce to merge the array.
So if you want to merge arrays inside an array while preserving numerical keys you can do it as follows:
<?php
$a = [
[0 => 'Test 1'],
[0 => 'Test 2', 2 => 'foo'],
[1 => 'Bar'],
];
print_r(array_reduce($a, function ($carry, $item) { return $carry + $item; }, []));
?>
Result:
Array
(
[0] => Test 1
[2] => foo
[1] => Bar
)
If you would like to:
check that each param going into array_merge is actually an array
specify a particular property within one of the arrays to merge by
You can use this function:
function mergeArrayofArrays($array, $property = null)
{
return array_reduce(
(array) $array, // make sure this is an array too, or array_reduce is mad.
function($carry, $item) use ($property) {
$mergeOnProperty = (!$property) ?
$item :
(is_array($item) ? $item[$property] : $item->$property);
return is_array($mergeOnProperty)
? array_merge($carry, $mergeOnProperty)
: $carry;
}, array()); // start the carry with empty array
}
Let's see it in action.. here's some data:
Simple structure: Pure array of arrays to merge.
$peopleByTypesSimple = [
'teachers' => [
0 => (object) ['name' => 'Ms. Jo', 'hair_color' => 'brown'],
1 => (object) ['name' => 'Mr. Bob', 'hair_color' => 'red'],
],
'students' => [
0 => (object) ['name' => 'Joey', 'hair_color' => 'blonde'],
1 => (object) ['name' => 'Anna', 'hair_color' => 'Strawberry Blonde'],
],
'parents' => [
0 => (object) ['name' => 'Mr. Howard', 'hair_color' => 'black'],
1 => (object) ['name' => 'Ms. Wendle', 'hair_color' => 'Auburn'],
],
];
Less simple: Array of arrays, but would like to specify the people and ignore the count.
$peopleByTypes = [
'teachers' => [
'count' => 2,
'people' => [
0 => (object) ['name' => 'Ms. Jo', 'hair_color' => 'brown'],
1 => (object) ['name' => 'Mr. Bob', 'hair_color' => 'red'],
]
],
'students' => [
'count' => 2,
'people' => [
0 => (object) ['name' => 'Joey', 'hair_color' => 'blonde'],
1 => (object) ['name' => 'Anna', 'hair_color' => 'Strawberry Blonde'],
]
],
'parents' => [
'count' => 2,
'people' => [
0 => (object) ['name' => 'Mr. Howard', 'hair_color' => 'black'],
1 => (object) ['name' => 'Ms. Wendle', 'hair_color' => 'Auburn'],
]
],
];
Run it
$peopleSimple = mergeArrayofArrays($peopleByTypesSimple);
$people = mergeArrayofArrays($peopleByTypes, 'people');
Results - Both return this:
Array
(
[0] => stdClass Object
(
[name] => Ms. Jo
[hair_color] => brown
)
[1] => stdClass Object
(
[name] => Mr. Bob
[hair_color] => red
)
[2] => stdClass Object
(
[name] => Joey
[hair_color] => blonde
)
[3] => stdClass Object
(
[name] => Anna
[hair_color] => Strawberry Blonde
)
[4] => stdClass Object
(
[name] => Mr. Howard
[hair_color] => black
)
[5] => stdClass Object
(
[name] => Ms. Wendle
[hair_color] => Auburn
)
)
Extra Fun:
If you want to single out one property in an array or object, like "name" from an array of people objects(or associate arrays), you can use this function
function getSinglePropFromCollection($propName, $collection, $getter = true)
{
return (empty($collection)) ? [] : array_map(function($item) use ($propName) {
return is_array($item)
? $item[$propName]
: ($getter)
? $item->{'get' . ucwords($propName)}()
: $item->{$propName}
}, $collection);
}
The getter is for possibly protected/private objects.
$namesOnly = getSinglePropFromCollection('name', $peopleResults, false);
returns
Array
(
[0] => Ms. Jo
[1] => Mr. Bob
[2] => Joey
[3] => Anna
[4] => Mr. Howard
[5] => Ms. Wendle
)
Try this
$result = array_merge($array1, $array2);
Or, instead of array_merge, you can use the + op which performs a union:
$array2 + array_fill_keys($array1, '');