Merge 2 arrays of objects in PHP [duplicate] - php

This question already has answers here:
Merging and group two arrays containing objects based on one identifying column value
(4 answers)
Closed last month.
How do you merge array1 and 2?
array1
Array
(
[0] => stdClass Object
(
[name] => bob
[id] => 84569354306
[contacts] => Array
(
[0] => none
)
)
[1] => stdClass Object
(
[name] => jill
[id] => 456745742
[contacts] => Array
(
[0] => none
)
)
)
array2
Array
(
[0] => stdClass Object
(
[name] => bob
[id] => 84569354306
[pid] => 1
[lang] => eng;
[location] =>
)
[1] => stdClass Object
(
[name] => jill
[id] => 456745742
[pid] => 2
[lang] => eng;
[location] =>
)
)
Result array:
Array
(
[0] => stdClass Object
(
[name] => bob
[id] => 84569354306
[pid] => 1
[lang] => eng;
[location] =>
[contacts] => Array
(
[0] => none
)
)
[1] => stdClass Object
(
[name] => jill
[id] => 456745742
[pid] => 2
[lang] => eng;
[location] =>
[contacts] => Array
(
[0] => none
)
)
)
I've tried an array_merge() which seems to add objects next to each other in the array rather than merging the objects.
I'm pretty sure this question is similar to what I need, but I'm having difficulty with the simple foreach loop.

You can cast the two objects to array and then re-cast back to an object. The general syntax is:
$merged = (object)array_merge_recursive((array)$firstObj, (array)$secondObj);
^
| note the recursive in your case
Also, if you are using objects like that maybe you should simply stick to array. It has very little to no sense to do something like that with objects
With multiple items
If you have multiple items you simply need to wrap up my script inside a loop:
function myCustomMerge($array1, $array2) {
assert('count($array1) == count($array2)');
$result = array();
foreach($array1 as $k=>$v) {
$item = array_merge_recursive((array)$array1[$k], (array)$array2[$k]);
$result[]=$item; // use (object)$item if you need objects
}
return $result;
}
Solution without casting
If you prefer not to cast back and forth between array and object you can use get_object_vars():
$obj2props = get_object_vars($obj2);
foreach ($obj2props as $prop => $value) {
$obj1->$prop = $value;
}
return $obj;

Another way of doing it:
function merge_values(){
$list = func_get_args();
while( count( $list ) > 1 ){
$array1 = array_shift( $list );
$array2 = array_shift( $list );
$merged_array = $array1;
foreach( $array2 as $key => $value ){
$merged_array[$key] = array_merge( (array)$value, (array)$merged_array[$key] );
if( is_object( $value ) || is_object( $array1[$key] ) ){
$merged_array[$key] = (object)$merged_array[$key];
}
}
array_unshift( $list, $merged_array );
}
return current( $list );
}
$merged = merge_values( $array1, $array2 );

Related

Array map, flatten and merge PHP

Array
(
[0] => Array
(
[id] => 1
[name] => Sister
[biological] => true
[sibling] => Array
)
[1] => Array
(
[id] => 2
[name] => Brother
[biological] => true
[sibling] => Array
(
[id] => 1
[name] => Brother1
[biological] => true
[sibling] => Array
)
(
[id] => 2
[name] => Sister1
[biological] => true
[sibling] => Array
)
)
)
I have here a multidimensional array
I am attempting to retrieve value from Brother under siblings array.
Ideally the end result should be like this:
Sisblings Array
(
"Sister"
"Brother"
"Brother1"
"Sister1"
)
I have tried foreach to catch the arrays but instead of returning all the siblings as intended, its overlapping the array under brothers siblings.
foreach ($tree['siblings'] as $i => $sibling) {
$tree['siblings'][$i]->siblings = $this->getRelationshipData($sibling->id, $region_id, $sibling_ids, $member->getKey());
foreach ($sibling->siblings ['sibligns'] as $j => $p) {
$tree['siblings'][$i]->siblings[$j]->relationship = $p->relationship;
}
return $tree;
You could also use a array_walk_recursive() to retrieve the data you need.
array_walk_recursive($array, function($val,$key) use(&$result){
if($key === "name") $result[] = $val;
});
The end result is the $result array.

How do i make one array out of two arrays containing different values

I have two arrays, one called fetched_services and one called fetched_companies, they look like this:
fetched_services
(
[1] => Array
(
[id] => 11
[child_services] => Array
(
[0] => Array
(
[id] => 153
)
[1] => Array
(
[id] => 137
)
[2] => Array
(
[id] => 138
)
)
)
)
fetched_companies
(
[0] => stdClass Object
(
[services] => Array
(
[0] => 25
[1] => 102
)
)
)
What i want to achieve is to end up with an array like fetched_services but only having child_services with id of fetched_companies["services"].
What i have tried is this:
$services = [];
$isFound = false;
foreach ($fetched_services as $fetched_service) {
foreach ($fetched_service["child_services"] as $fetched_child_service) {
$fetched_service["child_services"] = [];
foreach ($fetched_companies as $fetched_company) {
if( (in_array($fetched_child_service["id"],$fetched_company->services)) ) {
$fetched_service["child_services"][] = $fetched_child_service;
$isFound = true;
}
}
if($isFound) {
$services[] = $fetched_service;
$isFound = false;
}
}
}
This outputs this:
Array
(
[0] => Array
(
[id] => 11
[child_services] => Array
(
[0] => Array
(
[id] => 116
)
)
)
[1] => Array
(
[id] => 11
[child_services] => Array
(
[0] => Array
(
[id] => 117
)
)
)
)
As you can see the resulting array have two arrays containing same id but the child_services are different.
What i want to end up with is this:
Array
(
[0] => Array
(
[id] => 11
[child_services] => Array
(
[0] => Array
(
[id] => 116
)
)
(
[0] => Array
(
[id] => 117
)
)
)
)
What am i doing wrong here? Thanks!
Your question is a bit unclear (I'll edit/delete this if/when you clarify, see my comment above), but you could probably make use of array_filter by only keeping services that are present in said list (via in_array):
$result = array_filter(
$fetched_services['child_services'],
fn(array $child_service): bool => in_array($child_service['id'], $fetched_companies[0]->services, true)
);
Demo

PHP How to restructure an array?

I have an array that I'd like to restructure. I want to group items by turn. I can figure out how to extract data from the array using foreach($arr['history'] as $obj) my issue is with populating a new array using a loop.
Currently it looks like this:
Array (
[history] => Array (
[id] => 23452435
[legend] => Array (
[0] => Array (
[player] => me
[turn] => 1
[card] => Array (
[name] => foo
)
)
[1] => Array (
[player] => me
[turn] => 1
[card] => Array (
[name] => bar
)
)
[2] => Array (
[player] => opponent
[turn] => 1
[card] => Array (
[name] => derp
)
)
[3] => Array (
[player] => opponent
[turn] => 2
[card] => Array (
[name] => hoo
)
)
)
))
I want it to look like the following, but I can't figure out how to automatically create and populate this structure. This is an array with a sub-array for each turn, containing an array for me and opponent
Array (
[0] => Array (
[me] => Array (
[0] => foo
[1] => bar
)
[opponent] = Array (
[0] => derp
)
)
[1] => Array (
[me] => Array ()
[opponent] => Array (
[0] => hoo
)
))
Thanks.
Edit:
This is what I needed. Thanks for the answers.
$result = [];
foreach ($arr['history'] as $historyItem) {
foreach ($historyItem['legend'] as $list) {
$result[$list['turn']][$list['player']][] = $list['card']['name'];
}
}
Try this:
$result = [];
foreach ($data['history']['legend'] as $list) {
$result[$list['turn']-1][$list['player']][] = $list['card']['name'];
}
Fiddle it! http://ideone.com/BtKOKJ
You can just start adding data to the new array. PHP is extremely forgiving.
$historyByTurns = array();
foreach ($arr['history'] as $historyItem) {
foreach ($historyItem['legend'] as $legendItem) {
$turn = $legendItem['turn'];
$player = $legendItem['player'];
if (!array_key_exists($turn, $historyByTurns)) {
$historyByTurns[$turn] = array();
}
if (!array_key_exists($player, $historyByTurns[$turn])) {
$historyByTurns[$turn][$player] = array();
}
foreach ($legendItem as $card) {
$historyByTurns[$turn][$player][] = $card['name'];
}
}
}
You will have to test it, as I have no way to do that ATM.

Merge array values in a single array by removing duplicates and null values in PHP

I have an array like this:
Array
(
[0] => Array
(
[0] => Array
(
[id] => 1234
[name] => John
)
[1] => Array
(
)
)
[1] => Array
(
[0] => Array
(
[id] => 1234
[name] => John
)
[1] => Array
(
[id] => 5678
[name] => Sally
)
[2] => Array
(
[id] => 1234
[name] => Duke
)
)
My resulting array should be the following (basically merging and getting rid of duplicates and removing null values):
Array
(
[0] => Array
(
[id] => 1234
[name] => John
)
[1] => Array
(
[id] => 5678
[name] => Sally
)
[2] => Array
(
[id] => 1234
[name] => Duke
)
)
Is there an easy way to do this using PHP's array functions?
EDIT: So far I have this:
$result = array();
foreach ($array as $key => $value) {
if (is_array($value)) {
$result = array_merge($result, $value);
}
}
print_r($result);
Use array_merge to merge the arrays. Then use array_unique to remove duplicates. Finally, to remove null keys, use a loop.
foreach($array as $key=>$value)
{
if(is_null($value) || $value == '')
unset($array[$key]);
}
Documentation on these methods can be found here.
Flatten your unnecessarily depth array structure by unpacking the subarrays into a merge call.
Filter out the empty subarrays with array_filter().
Remove the duplicate subarrays with array_unique(). (SORT_REGULAR prevents "Warning: Array to string conversion")
Code: (Demo)
var_export(
array_unique(
array_filter(
array_merge(...$array)
),
SORT_REGULAR
)
);
Optionally, call array_values() on the resultant array to re-index it (remove the old keys).

Combine associative arrays php

How do I merge these associative arrays so that the indices ([0],[1]) are preserved and var_id, name and id are merged? I've tried array_combine and array_merge_recursive without succes.
Input
Array (
[0] => Array (
[var_id] => 43
)
[1] => Array (
[var_id] => 25
)
)
Array (
[0] => Array (
[name] => Tortoise
)
[1] => Array (
[name] => Black
)
)
Array (
[0] => Array (
[id] => 1907
)
[1] => Array (
[id] => 1908
)
)
Desired output
Array (
[0] => Array (
[var_id] => 43
[name] => Tortoise
[id] => 1907
)
[1] => Array (
[var_id] => 25
[name] => Black
[id] => 1908
)
)
Cheers,
Adnan
Assuming your three arrays are called $array1, $array2, and $array3 here's a loop that will do what you want:
foreach(array($array1, $array2, $array3) AS $array) {
foreach($array AS $key => $value) {
foreach($value AS $subkey => $subvalue) {
$final[$key][$subkey] = $subvalue;
}
}
}
Working example: http://3v4l.org/GY9oa
If you have an unknown number of input arrays to merge, it would be trivial to turn this into a function to handle that.

Categories