Complex array merge - php

I've been wrapping my head around this for a couple of days...
I have several arrays that need to be sort of merged into a single array. The order in which they merge is of great importance and is simply the order in which they appear in the global array (like the example below):
$input1 = array(
array(
'context' => 'aa', 'id' => 1, 'view' => 1, 'update' => 1,
),
array(
'context' => 'bb', 'id' => 2, 'view' => 0, 'update' => 0,
)
);
$input2 = array(
array(
'context' => 'cc', 'id' => 3, 'view' => 0, 'update' => 1,
),
array(
'context' => 'dd', 'id' => 4, 'view' => 0, 'update' => 0,
),
array(
'context' => 'ee', 'id' => 5, 'view' => 1, 'update' => 0,
)
);
$input3 = array(
array(
'context' => 'ff', 'id' => 6, 'view' => 1, 'update' => 1,
),
array(
'context' => 'gg', 'id' => 7, 'view' => 1, 'update' => 0,
),
);
$global = array($input1, $input2, $input3);
Each input array itself consists of several subarrays that are of equal structure; see http://pastebin.com/fQMUjUpB for an example. This pastebin code also includes the desired output.
The output array should contain:
a single level array
a tree-like passthrough upon "merging the next input array", viz. every possible cross-combination of subarrays should be made during a merge between two input arrays
the key of each a combination should be generated as a concatenated string of the corresponding context and id elements (glued with a plus) joined together with an ampersand (&); e.g: context1+id1&context2+id2
For the next merge the previous resulting array should be used in order for the example from above becomes
context1+id1&context2+id2&context3+id3
The resulting viewand update elements are calculated by simply multiplying their corresponding values during merge.
$output = array(
'aa+1&cc+3&ff+6' => array('view' => 0, 'update' => 1),
'aa+1&cc+3&gg+7' => array('view' => 0, 'update' => 0),
'aa+1&dd+4&ff+6' => array('view' => 0, 'update' => 0),
'aa+1&dd+4&gg+7' => array(...),
'aa+1&ee+5&ff+6' => array(...),
'aa+1&ee+5&gg+7' => array(...),
'bb+2&cc+3&ff+6' => array(...),
'bb+2&cc+3&gg+7' => array(...),
'bb+2&dd+4&ff+6' => array(...),
'bb+2&dd+4&gg+7' => array(...),
'bb+2&ee+5&ff+6' => array(...),
'bb+2&ee+5&gg+7' => array(...)
);
How can this be accomplished when looping over $global?
I may have expressed myself quite vaguely (it's really hard to explain!), but hopefully it becomes more clear when you take a look at the pastebin code...
Any help would be greatly appreciated!

Here's a minimal working code so that you can get the general idea (if you want to improve the code, feel free, there's a lot to do!):
function generate_output($globalArray, $context = array(), $view = 1, $update = 1, &$output = array()) {
if(!count($globalArray)) {
$output[implode('&', $context)] = array('view' => $view, 'update' => $update);
}
else {
foreach(reset($globalArray) as $elt) {
$newContext = $context;
$newContext[] = $elt['context'] . '+' . $elt['id'];
generate_output(array_slice($globalArray, 1), $newContext, $view * $elt['view'], $update * $elt['update'], $output);
}
}
return $output;
}
generate_output($global);

Related

Sum Integer with String and Merge With Same String - PHP

i have a problem with this array, i need get sum form string merge with same key
$data = array(
0 => array(
'name' => 'Alfa Edison, Dwiki',
'budget' => 3700,
),
1 => array(
'name' => 'Maverick Sam',
'budget' => 500,
),
2 => array(
'name' => 'Dwiki',
'budget' => 1000,
),
3 => array(
'name' => 'Steve, Dwiki',
'budget' => 2000,
),
4 => array(
'name' => 'Alfa Edison',
'budget' => 700,
),
5 => array(
'name' => 'Maverick Sam',
'budget' => 4000,
),
6 => array(
'name' => 'Steve, Alfa Edison',
'budget' => 334,
),
);
i want the result this:
array(
0 => array(
'name' => 'Alfa Edison',
'budget' => 4734,
),
1 => array(
'name' => 'Dwiki',
'budget' => 6700,
),
2 => array(
'name' => 'Maverick Sam',
'budget' => 4500,
),
3 => array(
'name' => 'Steve',
'budget' => 2334,
),
);
How to merge String with same Key and Sum the Budget. i try to for each but i'm fail.
i try array_reduce and explode the name but fail.
The problem is that each of the "keys" (names) is really more than one key. So as you iterate the input array you'll need to split those up, then add an inner loop to use the names as keys in the result.
foreach ($data as $item) {
// separate the names
$names = explode(', ', $item['name']);
// iterate the names and set/increase values for them in the result array
foreach ($names as $name) {
$result[$name]['name'] = $name;
$result[$name]['budget'] = $item['budget'] + ($result[$name]['budget'] ?? 0);
}
}
// remove the string keys if necessary
$result = array_values($result);

Sorting very long json object with php

I am working with an API and i am trying to sort the json object it returns to me. Here is a small cut out of the json object
Now i want to sort this because i only want to save part of the data. Say i wanted to save the "_ID" here. THe data i need is really way further down but i think if i can figure out how to get this, i can figure out the rest. Since as you can see from the picture, it contains many objects inside objects and arrays within arrays its very confusing for me to target the specific values i want
I have tried something like this:
$body = $response->getBody();
$data = json_decode($body, true);
$sortedData = $data."hits".hits[0]."_id";
return $sortedData
Also tried without the quotation marks, but i cant really get it to work. Im very new to PHP.
You decoded these objects into associative arrays, so $data['hits']['hits'][0]['_id'] should be the correct way to access that element.
https://www.php.net/manual/en/language.types.array.php explains the basics of how to work with arrays and access elements within them.
Since php 5.5, you can use array_column to get specific column from the array :
$body = $response->getBody();
$data = json_decode($body, true);
$sortedData = array_column($data, '_id');
return $sortedData;
Edit
From what I see on your array sample, you want to do a recursive multidimensional arrays search (not just 2-dimensional).
Assuming you have array like this :
$arr = array(
array(
'x' => '10',
'name' => 'blah',
'other' => array(
'_id' => '26',
'color' => '10x',
)
),
array(
'x' => '7',
'name' => 'blahblah',
'other' => array(
'_id' => '29',
'color' => '7x',
)
),
array(
'x' => '15',
'name' => 'blahblahblah',
'other' => array(
'_id' => '27',
'color' => '15x',
)
),
array(
'x' => '1',
'name' => 'sdf',
'other' => array(
'_id' => '41',
'color' => '1x',
)
),
array(
'x' => '4',
'name' => '3dgdg',
'other' => array(
'_id' => '31',
'color' => '4x',
)
),
array(
'x' => '5',
'name' => 'nmnmnm',
'other' => array(
'_id' => '36',
'color' => '5x',
)
),
array(
'x' => '21',
'name' => 'dhshshhh',
'other' => array(
'_id' => '34',
'color' => '21x',
)
)
);
And you want to get the _id key. In that case you could try this function :
function array_column_recursive(array $haystack, $needle) {
$found = [];
array_walk_recursive($haystack, function($value, $key) use (&$found, $needle) {
if ($key == $needle)
$found[] = $value;
});
return $found;
}
Usage :
$ids = array_column_recursive($arr,'_id');
sort($ids);
print_r($ids);
Reference :
array_column
array_column_recursive

Find element with duplicate key value and add new key using PHP

I have an array
$info = array(
[0] => array(
'id' => 1,
'uid' => '677674e21aed487fd7180da4a7619a9d'
),
[1] => array(
'id' => 1,
'uid' => 'd3c98a10fe4e42fb1fe868008c0f4cc1'
),
[2] => array(
'id' => 1,
'uid' => 'd3c98a10fe4e42fb1fe868008c0f4cc1'
),
[3] => array(
'id' => 1,
'uid' => '658284e5395a29bf34d21f30a854e965'
),
[4] => array(
'id' => 1,
'uid' => '01f33ae45a463e0c1de4ad989b3ccad5'
),
[5] => array(
'id' => 1,
'uid' => '677674e21aed487fd7180da4a7619a9d'
)
)
As you can see, uid of 0th index and 5th index are same. Similarly, uid of 2nd index and 3rd index are same.
I want a PHP script by which I can randomly create one hexadecimal color code for duplicate uids. Say something like this.
$info = array(
[0] => array(
'id' => 1,
'uid' => '677674e21aed487fd7180da4a7619a9d',
'col' => 'black'
),
[1] => array(
'id' => 1,
'uid' => 'd3c98a10fe4e42fb1fe868008c0f4cc1',
'col' => 'green'
),
[2] => array(
'id' => 1,
'uid' => 'd3c98a10fe4e42fb1fe868008c0f4cc1',
'col' => 'green'
),
[3] => array(
'id' => 1,
'uid' => '658284e5395a29bf34d21f30a854e965'
),
[4] => array(
'id' => 1,
'uid' => '01f33ae45a463e0c1de4ad989b3ccad5'
),
[5] => array(
'id' => 1,
'uid' => '677674e21aed487fd7180da4a7619a9d',
'col' => 'black'
)
)
How can I do this with the most minimum execution time?
There might be various ways for doing this workout, but due to lack of proper response, I came up with this probable lengthier code. I am posting the answer here for people who might need this.
$uidArray = array(); // creating a blank array to feed each uid
$uidDuplicateArray = array(); // creating a blank array as container to hold duplicate uid(s) only
foreach($all_data as $key => $ad)
{
// iterate through each item of the list
/.................
.................. //
$uidArray[] = $ad['uid'];
}
foreach(array_count_values($uidArray) as $val => $c)
{
if($c > 1)
{
// if count value is more than 1, then its duplicate
// set the uid duplicate array with key as uid and unique color code as value
$uidDuplicateArray[$val] = sprintf('#%06X', mt_rand(0, 0xFFFFFF));
}
}
foreach($all_data as $keyAgain => $adg)
{
// iterating through each item of original data
if(isset($uidDuplicateArray[$adg['uid']]))
{
// if the uid is key of the duplicate array, feed the value to original array in a new key.
$all_data[$keyAgain]['color'] = $uidDuplicateArray[$adg['uid']];
}
}
Each comment associated with each LOC is self explanatory.
The reason I wanted this, is to mark the duplicates in UI like this:-

JSON Array Construction PHP

I have part of a JSON feed that I need to segment based on variable existance, but its a nested array and I am not quite sure how to write it down.
Here is the code
$postData += array(
'LineItems' => array(
array(
'ItemName' => $_POST['milestone_1_detail'],
'Description' => 'Minimum Guarantee - Installment 1',
'Quantity' => 1,
'Price' => $_POST['milestone_1_amount'],
'SellComm' => 0,
'BuyComm' => 0,
'Accept' => true
),
array(
'ItemName' => $_POST['milestone_2_detail'],
'Description' => 'Minimum Guarantee - Installment 2',
'Quantity' => 1,
'Price' => $_POST['milestone_2_amount'],
'SellComm' => 0,
'BuyComm' => 0,
'Accept' => true
),
array(
'ItemName' => $_POST['milestone_3_detail'],
'Description' => 'Minimum Guarantee - Installment 3',
'Quantity' => 1,
'Price' => $_POST['milestone_3_amount'],
'SellComm' => 0,
'BuyComm' => 0,
'Accept' => true
)
)
);
As you can see, its three (potentially) items all listed in a parent array
I need to do a basic
if ($_POST['milestone_1_amount']) { LineItem1 }
if ($_POST['milestone_2_amount']) { LineItem2 }
if ($_POST['milestone_3_amount']) { LineItem3 }
type condition for all three items,that will still keep those child arrays in the parent array but ONLY show the lineItems that have a value set, but not quite sure how to correctly write the code and retain the array format
Thank you in advance for helping me to stop tearing my hair out

PHP - structure multidimensional array depending on values

I have an array:
$initialarray = array(
0 = array(
'unit' => 1,
'class' => 1,
'value' => 'string1'
),
1 = array(
'unit' => 1,
'class' => 2,
'value' => 'string2'
),
2 = array(
'unit' => 1,
'class' => 2,
'value' => 'string3'
),
3 = array(
'unit' => 2,
'class' => 1,
'value' => 'string4'
)
4 = array(
'unit' => 2,
'class' => 2,
'value' => 'string5'
)
);
What would be the best way to structure it (to group the resulting sub-arrays) depending first on the 'unit' field's values, and then depending on the 'class' field's values, like so:
$resultarray = array(
// array of all the sub-arrays of 'unit' = 1
$unit[1] = array(
// array of all the sub-arrays of 'unit' = 1 and 'class' = 1
$class[1] = array(
0 = array(
'unit' => 1,
'class' => 1,
'value' => 'string1'
)
)
// array of all the sub-arrays of 'unit' = 1 and 'class' = 2
$class[2] = array(
0 = array(
'unit' => 1,
'class' => 2,
'value' => 'string2'
),
1 = array(
'unit' => 1,
'class' => 2,
'value' => 'string3'
)
)
)
// array of all the sub-arrays of 'unit' = 2
$unit[2] = array(
// array of all the sub-arrays of 'unit' = 2 and 'class' = 1
$class[1] = array(
0 = array(
'unit' => 2,
'class' => 1,
'value' => 'string4'
)
)
// array of all the sub-arrays of 'unit' = 2 and 'class' = 2
$class[2] = array(
0 = array(
'unit' => 2,
'class' => 2,
'value' => 'string5'
)
)
)
)
I have asked a similar question here and got a working answer for only one iteration, i.e. for only structuring the array by one of the fields. But I could not make the same solution work for multiple iterations, i.e. for more than one field.
Also, is there a solution to structure a multidimensional array depending on more than two fields?
I think it's not a way of asking the question. It is very simple , you can do this by playing with arrays,keys and etc.... So first you should try hard for the problem. After If you have any problem in the middle of your tries then you can ask that here. I have solved your problem here is the complete code , but next time please do some work and then only post the problem. Never ask for the code.
foreach ($initialarray as $key1=>$val1)
{
foreach ($val1 as $key2=>$val2)
{
if($key2=='unit')
{
$num=$val2;
if($val2!=$num)
$testarr['unit'.$val2]=array();
}
if($key2=='class')
{
$testarr['unit'.$num]['class'.$val2][]=$val1;
}
}
}
print_r($testarr);
I must offer a better way for you and future researchers...
You only need one loop, and you merely need to nominate the result array's key values before using [] to "push" new data into the deepest subarray.
*there is absolutely no need for any condition statements or a second loop.
Code: (Demo)
$initialarray = [
['unit' => 1, 'class' => 1, 'value' => 'string1'],
['unit' => 1, 'class' => 2, 'value' => 'string2'],
['unit' => 1, 'class' => 2, 'value' => 'string3'],
['unit' => 2, 'class' => 1, 'value' => 'string4'],
['unit' => 2, 'class' => 2, 'value' => 'string5']
];
foreach ($initialarray as $row) {
$result[$row['unit']][$row['class']][] = $row;
}
var_export($result);
Output:
array (
1 =>
array (
1 =>
array (
0 =>
array (
'unit' => 1,
'class' => 1,
'value' => 'string1',
),
),
2 =>
array (
0 =>
array (
'unit' => 1,
'class' => 2,
'value' => 'string2',
),
1 =>
array (
'unit' => 1,
'class' => 2,
'value' => 'string3',
),
),
),
2 =>
array (
1 =>
array (
0 =>
array (
'unit' => 2,
'class' => 1,
'value' => 'string4',
),
),
2 =>
array (
0 =>
array (
'unit' => 2,
'class' => 2,
'value' => 'string5',
),
),
),
)
If I may express myself in the following manner: I only see the front-end of your problem and know nothing about its back-end, e.g. "Where does the data come from?", "How is it collected and stored", etc. so my answer might not be a real help but still I'll give my "tuppence".
If you can store all that data in a relational database (in form of table(s)) it would be much more easier and faster(!) to select the needed data from the database instead of rearranging arrays, which will take some more time in comparison.
Just as an example you might then select (and store it into an array) all items which have unit = '1' and / or all items which have class = '2'. That would make life much more easier IMHO, than having all the data in a multidimensional array and then try to sort it / rearrange it. Especially if you do that based on more than one property.

Categories