I'm trying to reduce/merge an array looking like this
$test = Array
(
[0] => Array
(
[id] => 150023
[rowtext] => part 1
[rowpartnumber] => 4360
[qty] => 2.00
[min_delper] => 2021-07-28
)
[1] => Array
(
[id] => 150026
[rowtext] => part 2
[rowpartnumber] => 4360
[qty] => 2.00
[min_delper] => 2021-07-29
)
[2] => Array
(
[id] => 150023
[rowtext] => part 3
[rowpartnumber] => 4361
[qty] => 4.00
[min_delper] => 2021-08-22
)
[3] => Array
(
[id] => 150023
[rowtext] => part 4
[rowpartnumber] => 4362
[qty] => 2.00
[min_delper] => 2021-09-22
)
);
I want to sum the [qty] where [rowpartnumber] are the same, I can achieve this with
$summa_test = array_reduce($test, function ($a, $b) {
isset($a[$b['rowpartnumber']]) ? $a[$b['rowpartnumber']]['qty'] += $b['qty'] : $a[$b['rowpartnumber']] = $b;
return $a;
});
But I would also like to take the [id] where [rowpartnumer] are the same and add it to [id]
so the output should look like this:
Array
(
[0] => Array
(
[id] => 150023 150026
[rowtext] => part 1
[rowpartnumber] => 4360
[qty] => 4.00
[min_delper] => 2021-07-28
)
[1] => Array
(
[id] => 150023
[rowtext] => part 3
[rowpartnumber] => 4361
[qty] => 4.00
[min_delper] => 2021-08-22
)
[2] => Array
(
[id] => 150023
[rowtext] => part 4
[rowpartnumber] => 4362
[qty] => 2.00
[min_delper] => 2021-09-22
)
);
Can't seem to get my head around it, so a little help from you experts would be great, thank you
You have to modify the callback function to concatenate the id to the previous one if the rowpartnumber already exits. Like this:
$summa_test = array_reduce($test, function ($carry, $item) {
if (isset($carry[$item['rowpartnumber']])) {
$carry[$item['rowpartnumber']]['qty'] += $item['qty'];
$carry[$item['rowpartnumber']]['id'] .= " ".$item['id'];
}
else {
$carry[$item['rowpartnumber']] = $item;
}
return $carry;
});
I don't know whether it is a problem, but because of the concatenation id will become a string where multiple ids are found - but remains integer when only one. If it is a problem for you, there are two options:
Convert to string even if only one id
Use an array to store to multiple ids.
(I changed the parameter names to the ones used in PHP documentation - you can change it back, but generally it is a good idea to keep that way - others will more easily understand your code.)
Related
This question already has answers here:
Sort an array of associative arrays by column value
(23 answers)
Closed 2 years ago.
I want to sort a nested array by number. So that in each category the products with the biggest number comes first.
I tried something i found here.
How to Sort Multi-dimensional Array by Value?
usort($myArray, function($a, $b) {
$retval = $a['order'] <=> $b['order'];
if ($retval == 0) {
$retval = $a['suborder'] <=> $b['suborder'];
if ($retval == 0) {
$retval = $a['details']['subsuborder'] <=> $b['details']['subsuborder'];
}
}
return $retval;
});
but found no solution to make it work. Especially because i don't know each productnumber (e.g.sdk38z3) inside one category (e.g. chocholate - sugar - candy).
In my case i used uasort instead of usort.
Array
(
[apple - oranges - bananas] => Array
(
[fn7z3] => Array
(
[slider_details] =>
[productnumber] => fn7z3
[category] =>
[title] =>
[text] =>
[picture] =>
[number] => 30
[oneString] =>
)
)
[chocholate - sugar - candy] => Array
(
[sdk38z3] => Array
(
[slider_details] =>
[productnumber] => sdk38z3
[category] =>
[title] =>
[text] =>
[picture] =>
[number] => 45
[oneString] =>
)
[g433] => Array
(
[slider_details] =>
[productnumber] => g433
[category] =>
[title] =>
[text] =>
[picture] =>
[number] => 2
[oneString] =>
)
[j8z28] => Array
(
[slider_details] =>
[productnumber] => j8z28
[category] =>
[title] =>
[text] =>
[picture] =>
[number] => 250
[oneString] =>
)
[73hf873] => Array
(
[slider_details] =>
[productnumber] => 73hf873
[category] =>
[title] =>
[text] =>
[picture] =>
[number] => 30
[oneString] =>
)
)
Result i want:
Array
(
[apple - oranges - bananas] => Array
(
[fn7z3] => Array
(
[slider_details] =>
[productnumber] => fn7z3
[category] =>
[title] =>
[text] =>
[picture] =>
[number] => 30
[oneString] =>
)
)
[chocholate - sugar - candy] => Array
(
[j8z28] => Array
(
[slider_details] =>
[productnumber] => j8z28
[category] =>
[title] =>
[text] =>
[picture] =>
[number] => 250
[oneString] =>
)
[sdk38z3] => Array
(
[slider_details] =>
[productnumber] => sdk38z3
[category] =>
[title] =>
[text] =>
[picture] =>
[number] => 45
[oneString] =>
)
[73hf873] => Array
(
[slider_details] =>
[productnumber] => 73hf873
[category] =>
[title] =>
[text] =>
[picture] =>
[number] => 30
[oneString] =>
)
[g433] => Array
(
[slider_details] =>
[productnumber] => g433
[category] =>
[title] =>
[text] =>
[picture] =>
[number] => 2
[oneString] =>
)
)
I finally found a solution for my problem, by using a function given in this answer:
How to sort an array of associative arrays by value of a given key in PHP?
Because i don't really know the key i need i used a foreach loop with the $key functionality.
I needed to override my actual array with the sorted array too, to make changes permanent.
In my case, as i said, im using uasort instead of usort, because im using names as Key.
Explanation of variables:
$similarProducts = my whole array.
$attributeCombination = for Example [apple - oranges - bananas]
function invenDescSort($item1, $item2)
{
if ($item1['number'] == $item2['number']) return 0;
return ($item1['number'] < $item2['number']) ? 1 : -1;
}
foreach ($similarProducts AS $key => $attributeCombination) {
uasort($attributeCombination, 'invenDescSort');
$this->similarProducts[$key] = $attributeCombination;
//print_r($attributeCombination);
}
I have made researches and havent fount any solutions for this yet. So final thought is come to Stackoverflow and ask the question.
I have 2 array like below:
BigArray
Array
(
[0] => Array
(
[id] => 1
[category_name] => Accountancy
[category_name_vi] => Kế toán
[category_id] => 1
)
[1] => Array
(
[id] => 2
[category_name] => Armed forces
[category_name_vi] => Quân đội
[category_id] => 2
)
[2] => Array
(
[id] => 3
[category_name] => Admin & Secretarial
[category_name_vi] => Thư ký & Hành chính
[category_id] => 3
)
[3] => Array
(
[id] => 4
[category_name] => Banking & Finance
[category_name_vi] => Tài chính & Ngân hàng
[category_id] => 4
)
)
and SmallArray:
Array
(
[0] => Array
(
[id] => 7
[category_id] => 2
[jobseeker_id] => 1
)
[1] => Array
(
[id] => 8
[category_id] => 3
[jobseeker_id] => 1
)
)
Ok, now I wanted to match each category_id from SmallArray link with respectively category_name from BigArrayand the output I only need matched values between SmallArray and BigArraywhere category_id of SmallArray is key and category_name of BigArray is value like below:
Matched array:
Array
(
[0] => Array
(
[2] => Armed forces
)
[1] => Array
(
[3] => Admin & Secretarial
)
)
So far, I have tried array_intersect, 2 foreach loops but no luck. Any advise would be very appreciated :(
Thanks
This should do that:
foreach ($smallArray as $smallKey => $smallElement) {
foreach ($bigArray as $bigKey => $bigElement) {
if ($bigElement['id'] == $smallElement['category_id']) {
$smallArray[$smallKey] = array(
$bigElement['id'] => $bigElement['category_name'],
);
break; // for performance and no extra looping
}
}
}
After these loops, you have what you want in $smallArray.
I have below $test array
Array
(
[0] => Array
(
[quantity] => 3
[stock_id] => _PHONE
)
[1] => Array
(
[quantity] => 3
[stock_id] => 102
)
[2] => Array
(
[quantity] => 4
[stock_id] => _PHONE
)
[3] => Array
(
[quantity] => 3
[stock_id] => 102
)
[4] => Array
(
[quantity] => 4
[stock_id] => _PHONE
)
[5] => Array
(
[quantity] => 6
[stock_id] => _PHONE
)
[6] => Array
(
[quantity] => 2
[stock_id] => 102
)
)
and to sum same stock_id keys to one, i use below functions:
function sum($array, $key){
isset($array[$key['stock_id']]) ? $array[$key['stock_id']]['quantity'] += $key['quantity'] : $array[$key['stock_id']] = $key;
return $array;
};
//merge same stock_id and sum the quantity same stock id
$sum_same_stock_id = array_reduce($test, "sum");
and the result went well like below:
$sum_same_stock_id:
Array
(
[_PHONE] => Array
(
[quantity] => 17
[stock_id] => _PHONE
)
[102] => Array
(
[quantity] => 8
[stock_id] => 102
)
)
So the question here is, I wanted to pass an dynamic keys values not just fixed values stock_id & quantity in sum function above. Have tried variety ways but still can't figured out the way. And can we put those functions into class as well?
Any advise is appreciated!
Maybe you can use the "use" function for the callback?
See https://www.php.net/manual/en/functions.anonymous.php
Q: How to Search Massive Multi-Dimensional Array for Single Value, and Return Parent Array?
I have this massive json that represents all of the achievements in WoW.
http://us.battle.net/api/wow/data/character/achievements
I converted it into an array using json_decode. This then leaves me with a very massive array that I need to search all of its levels until I find a specific value, I then need to return the parent array of that value.
ex:
This is one small part of the decoded array.
[0] => Array
(
[id] => 7385
[title] => Pub Crawl
[points] => 10
[description] => Complete the Brewmaster scenario achievements listed below.
[reward] => Reward: Honorary Brewmaster Keg
[rewardItems] => Array
(
[0] => Array
(
[id] => 87528
[name] => Honorary Brewmaster Keg
[icon] => inv_holiday_brewfestbuff_01
[quality] => 3
[itemLevel] => 90
[tooltipParams] => Array
(
)
[stats] => Array
(
)
[armor] => 0
)
)
[icon] => inv_misc_archaeology_vrykuldrinkinghorn
[criteria] => Array
(
[0] => Array
(
[id] => 20680
[description] => Spell No Evil
[orderIndex] => 0
[max] => 1
)
[1] => Array
(
[id] => 20681
[description] => Yaungolian Barbecue
[orderIndex] => 1
[max] => 1
)
[2] => Array
(
[id] => 20682
[description] => Binan Village All-Star
[orderIndex] => 2
[max] => 1
)
[3] => Array
(
[id] => 20683
[description] => The Keg Runner
[orderIndex] => 3
[max] => 1
)
[4] => Array
(
[id] => 20684
[description] => Monkey in the Middle
[orderIndex] => 4
[max] => 1
)
[5] => Array
(
[id] => 20685
[description] => Monkey See, Monkey Kill
[orderIndex] => 5
[max] => 1
)
[6] => Array
(
[id] => 20686
[description] => Don't Shake the Keg
[orderIndex] => 6
[max] => 1
)
[7] => Array
(
[id] => 20687
[description] => Party of Six
[orderIndex] => 7
[max] => 1
)
[8] => Array
(
[id] => 20688
[description] => The Perfect Pour
[orderIndex] => 8
[max] => 1
)
[9] => Array
( re
[id] => 20689
[description] => Save it for Later
[orderIndex] => 9
[max] => 1
)
[10] => Array
(
[id] => 20690
[description] => Perfect Delivery
[orderIndex] => 10
[max] => 1
)
)
[accountWide] =>
[factionId] => 2
)
I am attempting to create a function where I can just simply enter the achievement ID, which in this exmple is 7385, and have the parent array which would be [0] => Array (...); returned, so i can then grab the achievement details from that array.
I am not sure if this is really a proper question, as I am not sure as where to start.
So far I have just started breaking the original massive array down into its 10 equally as massive categories, and then searching them each individually, but I would like to just be able to search the main array once instead of searching each category array individually.
ex:
$allAchieves = file_get_contents('http://us.battle.net/api/wow/data/character/achievements');
$allAchieves = json_decode($allAchieves, true);
$generalAchieves = $allAchieves[achievements][0][achievements];
$quests = $allAchieves[achievements][1][categories];
$explorationAchieves = $allAchieves[achievements][2][categories];
$pvp = $allAchieves[achievements][3][categories];
$dungeonAndRaids = $allAchieves[achievements][4][categories];
$professions = $allAchieves[achievements][5][categories];
$reputation = $allAchieves[achievements][6][categories];
$scenarios = $allAchieves[achievements][7][categories];
$worldEvents = $allAchieves[achievements][8][categories];
$petbattle = $allAchieves[achievements][9][categories];
$featsOfStrength = $allAchieves[achievements][10][categories];
Hopefully someone can help, as the other threads I have seen sofar on array searching seem too simple to be of any help as the arrays they are dealing with are nothing to the size of the one I have here.
Thanks for the suggestions, but I solved the issue using a different approach found here:
http://us.battle.net/wow/en/forum/topic/8892160022?page=1#4
This code builds an array:
$size = sizeof($include_quotes);
for ($i=0; $i<$size; $i++) {
$quotes = $GLOBALS[$include_quotes[$i]]->quote($method);
if (is_array($quotes)) $quotes_array[] = $quotes;
}
}
If i
print_r($quotes_array);
i get the following:
Array ( [0] => Array ( [id] => advshipper [methods] => Array ( [0] => Array ( [id] => 1-0-0 [title] => Trade Shipping [cost] => 20 [icon] => [shipping_ts] => [quote_i] => 0 ) [1] => Array ( [id] => 2-0-0 [title] => 1-2 working days [cost] => 3.2916666666667 [icon] => [shipping_ts] => [quote_i] => 1 ) [2] => Array ( [id] => 4-0-0 [title] => 2-3 working days [cost] => 2.4916666666667 [icon] => [shipping_ts] => [quote_i] => 2 ) [3] => Array ( [id] => 8-0-0 [title] => Click & Collect [cost] => 0 [icon] => [shipping_ts] => [quote_i] => 3 ) ) [module] => Shipping [tax] => 20 ) )
In some circumstances, I only want the data in field 0 to be passed onto the next part of the code. However, using
$sliced_quotes_array = array_slice($quotes_array,0,1);
Still returns all the results.
What is the correct method to get just:
Array ( [0] => Array ( [id] => advshipper [methods] => Array ( [0] => Array ( [id] => 1-0-0 [title] => Trade Shipping [cost] => 20 [icon] => [shipping_ts] => [quote_i] => 0 )
Any help greatly appreciated because i have tried numerous different ways and no luck yet.
Using the following still returns the same results
$testarray = array(0 => $quotes_array[0]);
print_r($testarray);
Why not just use the array constructor and explicitly include what you need:
array(0 => $quotes_array[0]);
Here is your array:
When you are saying " I only want the data in field 0 to be passed onto the next part of the code", you meant that you only want this data to be passed next, right? :
Array (
[0] => Array (
[id] => advshipper
[module] => Shipping
[tax] => 20
)
)
Is this what you want?
$newArray = array();
foreach ($quotes_array[0] as $items)
{
if (!is_array($items))
{
$newArray[] = $items;
}
}
$newArray will contain that data.
UPDATE
Okay, gotcha.
You can just use this:
$newArray = $quotes_array[0]['methods'][0];
Having done some reading on arrays and after a bit of trial, i found a solution to my problem.
I used:
unset($quotes_array[0]['methods'][1]);
By changing the index number after methods i was able to drop any shipping options i didn't require, whilst still maintaining the functionality.