How to merge two arrays of objects [duplicate] - php

This question already has answers here:
Merge rows of two arrays containing objects by first level index
(3 answers)
Closed 5 months ago.
A:
Array (
[0] => gapiReportEntry Object (
[metrics:private] => Array (
[visits] => 1036
[pageviews] => 2046
[bounces] => 693
[entrances] => 1036
)
[dimensions:private] => Array (
[date] => 20110114
)
)
)
B:
Array (
[0] => gapiReportEntry Object (
[metrics:private] => Array (
[goal1Completions] => 1
)
[dimensions:private] => Array (
[date] => 20110114
)
)
)
C:
Array (
[0] => gapiReportEntry Object (
[metrics:private] => Array (
[visits] => 1036
[pageviews] => 2046
[bounces] => 693
[entrances] => 1036
[goal1Completions] => 1
)
[dimensions:private] => Array (
[date] => 20110114
)
)
)
I want to merge(A,B) and get C.

I don't know the reason of such question, but here is solution:
//lets think $A - A - array, $B - B array
$a1 = (array)$A[0];
$b1 = (array)$B[0];
$c = array_merge($a1, $b1);
print_r($result);
//shows your Array, but not object.
//You can create object using printed resulted array.

For your specific case, let's be clear that you want to merge two arrays that are contained within objects contained within arrays. That being said, knowing how the resultant object was to be used (do you just need the data from those arrays, or does the rest of the object's instance matter?) would help give you an answer. tl;dr:
$temparray = array_merge($A[0]->metrics, $B[0]->metrics);
$C->methodToSetMetricsArray($temparray);
Where the above methodToSetMetricsArray() does what it says, since the array is private and can't be set directly.

First of all I'm not saying this is the end all of answers to this question, but it's been nine months and I feel the question hasn't been answered, while it does have it's uses.
From what I understand you have two (or more) arrays, consisting of multiple objects, who hold different attributes of the same object. As for instance in the next example:
ArrayedObjects1=array(
[0]=>stdClass Object
(
[id] => 1
[name] => foo
)
[1] => stdClass Object
(
[id] => 51
[name] => bar
)
)
ArrayedObjects2=array(
[0]=>stdClass Object
(
[length] => 195
[color] => blue
)
[1] => stdClass Object
(
[length] => 100
[name] => purple
)
)
Use cases could be for very large projects where multiple databases are used to store single values of the same object and simple join queries aren't possible.
These two arrays can be joined by using two functions I made, which simply allow for a unspecified amount of arrays to be joined together.
class FooBar {
public function mergeArrayedObjects(){
# We generate a new empty array to return from the function, to which we merge the existing arrays
$returnResponse=array();
# Then we establish the the number of arguments passed to the function
$numArgs=func_num_args();
# As objects are stored within an array of equal length, we loop through the first
for($i=0;$i<count(func_get_arg(0));$i++){
# For each key within the array we merge all existing arrays. We get this number from the number of arguments
# First we check if there already exists an entry into the returnRespone array with the current key. Two choices:
# Case 1 => no: create one by merging the first two arrays into this new array
# Case 2 => yes: merge the existing entry with the next array and recreate it
# BTW we correct $numArgs in the for-loop, as we add 1 to $j in the second case to exclude duplication of work
for($j=0;$j<($numArgs-1);$j++){
# Seems like you can't check on empty with func_get_arg(), so store it in a variable
# We do this as no merge is needed if the array is empty, or the key is empty
$isempty=func_get_arg($j+1);
if(!empty($isempty)||!empty($isempty[$i])){
if(!$returnResponse[$i]){
$array1=func_get_arg($j);
$array2=func_get_arg($j+1);
$returnResponse[$i]=self::mergeObjects($array1[$i],$array2[$i]);
}
else{
$array1=func_get_arg($j+1);
$returnResponse[$i]=self::mergeObjects($returnResponse[$i],$array1[$i]);
}
}
}
}
# Then we return the arrayed objects
return $returnResponse;
}
public function mergeObjects($obj1,$obj2){
# Function to merge objects
$merged_obj= (object) array_merge((array) $obj1, (array) $obj2);
return $merged_obj;
}
}
This returns the following array:
$joinArrays=new FooBar;
$joinedArray=$joinArrays->mergeArrayedObjects(ArrayedObjects1,ArrayedObjects2);
$joinedArray=array(
[0]=stdClass Object
(
[id] => 1
[name] => foo
[length] => 195
[color] => blue
)
[1] => stdClass Object
(
[id] => 51
[name] => bar
[length] => 100
[name] => purple
)
)
As I said this can be used for an unlimited amount of arrays. If there's a faster way, feel free to let me know. I needed this for joining the results from queries between different DB's so I just wrote to as this does the job and is quite flexible at the same time.
This can also be extended to check if one of the entries within the object is an array and do an array_merge ofcourse, it would add two lines of code.

You want a deep merge with custom Php class. There is no such function built-in.
But if you can transform your Php objects to array, you could get advantage of array_merge_recursive functions (see http://php.net/manual/fr/function.array-merge-recursive.php).

Related

Find if all elements in one multidimensional arrays exists in another (using a multidimensional array as a haystack)

I have been trying to use some logic to be able to see if all elements in a multidimensional array (haystack) exits in another much larger haystack. My first haystack comes from a json object in the first place, and the second one is a "dot name" string, that is also converted into an array. The logic here is that I can use a string describing what I'm looking for in the json in a simple way:
Needle:
Array
(
[key1] => Array
(
[provider] => Array
(
[id] => 1
)
)
[key2] => Array
(
[consumer] => Array
(
[id] => 5
)
[hostname] => foo
)
)
Haystack:
[0] => Array
(
[id] => 1000
[consumer] => Array
(
[id] => 5
[name] => test
[hostname] => foo
[1] => Array
(
[id] => 1200
[provider] => Array
(
[id] => 5
[name] => test
If the needle exists in the array the top key should be returned. So if we pretend all key->values below "key2" exists in array we should return key2. provider-id and consumer-id are not the same and there might be other key-values that might look the same, but has a different path. so if "hostname" would exists, but much deeper into array that is not a match.
The problem is that all examples I've come across either have:
A fixed depth on the array.
Having the needle as a string.
Is not true multidimensional.
Is there a way this can be done? recursiveiteratoriterator did come to my mind but not sure actually how to use it, based on the above.
I've also looked at various in_array/is_array/array_map/array_filter recursive examples but they are fell a bit messy and I couldn't decide if it was worth trying to build something that would allow to crawl two arrays in a good way.
My array is quite large and contains, sadly mostly items I'm not interested in. But if I can find a way that works I'm sure I can optimize that part.
Thanks for reading.

Searching complex array for and modifying a value in php

I have a complex multi-dimensional array that looks something like
[name] => Marko Polo
[description] => New application
[number] => ABCD1234
[loans] => Array
(
[0] => Array
(
[id] => 123
[application_id] => 456
[loan_fees] => Array
(
)
[loan_parts] => Array
(
[0] => Array
(
[id] => 987
[loan_id] => 123
[product_id] => 49788
[product] => Array
(
[id] => 49788
[lender] => MAC
...
I need to create an efficient way of traversing this array and, for example having a set of rules to filter/modify the data.
For example, in the array there is [lender] => MAC, I want to have something like
loans.loan_parts.product.lender.MAC = 'Macquarie'
This would be in a config of sorts such that if the data array changed, it would be simply a matter of changing that dot notation to point to the new location of the lender value.
Using this, I need to filter the lender and modify it to be Macquarie instead of Mac.
I know that a big no-no these days is using too many foreach loops and I've looked into Collections, but because the inner arrays are not named, I don't believe Collections is possible.
As I say, I'd like to avoid the situation of
foreach
foreach
if (is_array())
foreach
eeewww!
How can I execute this in the most efficient manner due to the possible large size of the array and its complexity.
You can use array_walk_recursive with callback that will change behavior according to key of array.
<?php
//can pass variable by reference to change array in function
function handleMAC(&$item, $key)
{
if($key == 'lender'){
$item['MAC'] = 'your value';
}
}
array_walk_recursive($array, 'handleMAC');
?>

Accessing an array in an object

In PHP I printed return '<pre>'.print_r($getFileId,true).'</pre>'; which is an object. This returns:
<pre>Illuminate\Support\Collection Object
(
[items:protected] => Array
(
[0] => 1
[1] => 2
[2] => 3
)
)
How can I access the last element of the array. Tried end($getFileId) but it returned:
<pre>Array
(
[0] => 1
[1] => 2
[2] => 3
)
</pre>
Your Illuminate object has a method specifically for this purpose:
$getFileId->last();
Please see the docs for more information
Apparently your $getFileId variable is a Collection object, not an array. That's why calling the end function on it does not work, but it doesn't fail either because it implements ArrayAccess.
You could do it in many ways:
end($getFileId->all());
$getFileId->flip()->first();
//beware, this one alters the collection by also removing the last element
$getFileId->pop();
$getFileId->slice($getFileId->count() - 1, 1)->first();
But all these would be just running in circles when you could simply do:
$getFileId->last();

Nested array in php

I'm having trouble handling a nested array I get as result from an API. Print_r($result, true); returns an array looking like this (only much longer):
Array
(
[success] => 1
[return] => Array
(
[sellorders] => Array
(
[0] => Array
(
[sellprice] => 0.00000059
[quantity] => 1076.00000000
[total] => 0.00063484
)
[1] => Array
(
[sellprice] => 0.00000060
[quantity] => 927.41519000
[total] => 0.00055645
)
)
[buyorders] => Array
(
[0] => Array
(
[buyprice] => 0.00000058
[quantity] => 6535.77328102
[total] => 0.00379075
)
[1] => Array
(
[buyprice] => 0.00000057
[quantity] => 118539.39620414
[total] => 0.06756746
)
)
)
)
I need to grab the 3 values (sellprice/buyprice, quantity, total) from the first index of both arrays (sellorders and buyorders) and store them in variables ($sellprice, $sellquantity, $selltotal).
The full example php script I'm using can be found on the bottom of this page. Could anyone help me figure this out?
In php, arrays can more or less have infinite dimensions. You can go deeper within an array's dimensions by adding another set of square brackets. For example,
$array['deep']['deeper']['deepest'][0];
Assuming the indexes in the sellorders and buyorders are the same in your array, you could do
$sellprice = $result['return']['sellorders'][0]['sellprice'];
$sellquantity = $result['return']['sellorders'][0]['quantity'];
$selltotal = $result['return']['sellorders'][0]['total'];
The value should look something like this:
$sellprice = $array['return']['sellorders'][0]['sellprice']
You might want to think about how you iterate over these nested arrays in order to pick out all the values. Furthermore, if you have control over the output I might be better to use a different data structure to enable easier processing.
You can access the values of the nested arrays by adding another pair of square brackets with the appropriate index at the end:
$array['outer']['inner'];
It's up to you to transfer this knowledge to your specific array.
If you want to go thru all of those arrays... try this:
for($i=0; $i<count($array['return']['sellorders']); $i++) {
$this_array = $array['return']['sellorders'][$i];
var_dump($this_array); // it includes sellprice, quantity and total for each entity now.
}
use the same method as above for buyorders as well.

Sorting Multidimensional Array

Thought I will point out first that I have looked around on Stackoverflow and the internet already and although they are plenty of examples none of them are explained into such a way for me to understand how to convert the code to work with my array structure.
I believe I need to use one of the functions uksort or uasort but unsure on this as well.
My array looks like the following.
Array
(
[0] => Array
(
[Result] => Array
(
[id] => 260
[event_id] => 72
[year] => 2010
[york_score] => 27
[york_points] => 0.0
[lancs_score] => 51
[lancs_points] => 4.0
[winner] => L
[confirmed] => Y
[updated] => 2010-05-01 16:10:03
)
[Event] => Array
(
[id] => 72
[sport_id] => 25
[event_title] => 1st Team
[Sport] => Array
(
[id] => 25
[sport_title] => Netball
)
)
)
And where its [0] means it continues on.
I need to sort all of the arrays [0,1,2,3,...] by the sport_title key found in [Event][Sport]
Does anyone know how to create a sorting function to do this?
Some explanation of how the function is working would also be helpful if I later need to adapter/alter the code to work else where on my site.
Where $array is the name of the array which holds the array you posted in your question.
function sort_multi($item_1, $item_2)
{
// strcmp looks at two strings and, based off the characters' and their order,
// determines which one is numerically greater. When this function returns a
// negative, for example, it means the first item it's comparing is less that the
// second item (ef and eg, for example). The usort function then rearranges
// the array based off these comparisons.
return strcmp($item_1['Event']['Sport']['sport_title'], $item_2['Event']['Sport']['sport_title']);
}
usort($array, 'sort_multi');

Categories