Having some problem grouping a simple Array. Would like to group sizes and sum quantity. These are shoe sizes.
This is my array:
Array
(
[0] => Array
(
[sku] => '82368-21'
[size] => 36
[quantity] => 1
)
[1] => Array
(
[sku] => '82368-21'
[size] => 36
[quantity] => 3
)
[2] => Array
(
[sku] => '82368-22'
[size] => 38
[quantity] => 0
)
[3] => Array
(
[sku] => '82368-23'
[size] => 39
[quantity] => 2
)
[4] => Array
(
[sku] => '82368-23'
[size] => 39
[quantity] => 1
)
)
As you can see the shoes has multiple sizes and its quantity. There
is no need to remove any duplicates as they should all group by size.
I would like to output the following:
Array
(
[0] => Array
(
[sku] => '82368-21'
[size] => 36
[quantity] => 4
)
[1] => Array
(
[sku] => '82368-22'
[size] => 38
[quantity] => 0
)
[2] => Array
(
[sku] => '82368-23'
[size] => 39
[quantity] => 3
)
)
You can do this with a simple foreach loop:
$array = array (
0 =>
array (
'size' => 36,
'quantity' => 1
),
1 =>
array (
'size' => 36,
'quantity' => 3
),
2 =>
array (
'size' => 38,
'quantity' => 0
),
3 =>
array (
'size' => 39,
'quantity' => 2
),
4 =>
array (
'size' => 39,
'quantity' => 1
)
);
$out = [];
foreach($array as $value){
$key = $value['size'];
if(!isset($out[$key])){
$out[$key] = $value;
}else{
$out[$key]['quantity'] += $value['quantity'];
}
}
print_r($out);
Output
Array
(
[36] => Array
(
[size] => 36
[quantity] => 4
)
[38] => Array
(
[size] => 38
[quantity] => 0
)
[39] => Array
(
[size] => 39
[quantity] => 3
)
)
Sandbox
I think the thing you were missing was using the size as the key. With arrays when you want to group or combine things with a single value match, it's best to take that value and use it as the array key. That just makes it easier to find the group in the output array. Once your done with it you can always use array_values to reset the keys to "normal" numbered indexs.
//reset the array keys
$out = array_values($out);
print_r($out);
Output
Array
(
[0] => Array
(
[size] => 36
[quantity] => 4
)
[1] => Array
(
[size] => 38
[quantity] => 0
)
[2] => Array
(
[size] => 39
[quantity] => 3
)
)
Sandbox
Cheers
Related
I have a multidimensional array, I want to take the key 'data' from each array item and form another array, like first array 'data' element has 3 items, second has 1 item, 3rd and 4th are empty, and 5th has one item, I want to make a separate array like $temp_array['first_item_from_first_array,..., first_item_from_fifth_array, 'second_item_from_second_array,....,second_item_From_fifth_array]
input array is,
Array
(
[0] => Array
(
[meal_type] => bf
[label] => Breakfast
[calorie_limit] => 30
[total_calorie] => 0
[data] => Array
(
[0] => Array
(
[id] => 109
[label] => testfrom
[quantity] => 12
[unit] => g
)
[1] => Array
(
[id] => 118
[label] => test
[quantity] => 200
[unit] => oz
)
[2] => Array
(
[id] => 121
[label] => test
[quantity] => 10
[unit] => g
)
)
)
[1] => Array
(
[meal_type] => sn
[label] => Snacks
[calorie_limit] => 10
[total_calorie] => 0
[data] => Array
(
[0] => Array
(
[id] => 120
[label] => testfrom
[quantity] => 12
[unit] => g
)
)
)
[2] => Array
(
[meal_type] => lu
[label] => Lunch
[calorie_limit] => 20
[total_calorie] => 0
[data] => Array
(
)
)
[3] => Array
(
[meal_type] => su
[label] => Supper
[calorie_limit] => 30
[total_calorie] => 0
[data] => Array
(
)
)
[4] => Array
(
[meal_type] => dn
[label] => Dinner
[calorie_limit] => 20
[total_calorie] => 0
[data] => Array
(
[0] => Array
(
[id] => 119
[label] => test
[quantity] => 200
[unit] => oz
)
)
)
)
the output to be like this
Array
(
[0] => Array
(
[0] => Array
(
[id] => 109
[label] => testfrom
[quantity] => 12
[unit] => g
)
[1] => Array
(
[id] => 120
[label] => testfrom
[quantity] => 12
[unit] => g
)
[2] => Array
(
)
[3] => Array
(
)
[4] => Array
(
[id] => 119
[label] => test
[quantity] => 200
[unit] => oz
)
)
[1] => Array
(
[0] => Array
(
[id] => 118
[label] => test
[quantity] => 200
[unit] => oz
)
[1] => Array
(
)
[2] => Array
(
)
[3] => Array
(
)
[4] => Array
(
)
)
[2] => Array
(
[0] => Array
(
[id] => 121
[label] => test
[quantity] => 10
[unit] => g
)
[1] => Array
(
)
[2] => Array
(
)
[3] => Array
(
)
[4] => Array
(
)
)
)
You need to do it like below:-
$data_array= array_column($array,'data');
$count = 0;
foreach($data_array as $data){
$real_count = count($data);
if($real_count > $count){
$count = $real_count;
}
}
echo $count;
$final_array = [];
foreach($data_array as $data_arr){
for($i=0;$i< $count; $i++){
$final_array[$i][] = (count($data_arr[$i])>0)? $data_arr[$i]: array();
}
}
echo "<pre/>";print_r($final_array);
Output:-https://eval.in/925383
Reference:- PHP: array_column - Manual
You can use array_column() function
Example :-
<?php
$array = [
[
"meal_type" => "bf",
"data" => [
"name" => "test",
"email" => "test#ymail.com"
]
],
[
"meal_type" => "bf",
"data" => []
]
];
echo "<pre>";
print_r(array_column($array, "data"));
?>
You can do this using foreach and array_push.
$data_item_array = [];
foreach ($array as $item) {
$data = $item['data'];
foreach ($data as $t) {
array_push($data_item_array, $t);
}
}
print_r($data_item_array);
Output will be :
Array
(
[0] => Array
(
[id] => 109
[label] => testfrom
[quantity] => 12
[unit] => g
)
[1] => Array
(
[id] => 118
[label] => test
[quantity] => 200
[unit] => oz
)
[2] => Array
(
[id] => 121
[label] => test
[quantity] => 10
[unit] => g
)
[3] => Array
(
[id] => 120
[label] => testfrom
[quantity] => 12
[unit] => g
)
[4] => Array
(
[id] => 119
[label] => test
[quantity] => 200
[unit] => oz
)
)
This is the original main array:
Array
(
[0] => Array
(
[subtotal] => 0.6000
[taxes] => 0.0720
[charged_amount] => 0.6720
[total_discount] => 0.0000
[provinceName] => BC
[store_key] => 1
[store_id] => 5834
[categories] => Array
(
[2] => 0.6000
[4] => 0
[3] => 0
)
)
[1] => Array
(
[subtotal] => 29.8500
[taxes] => 2.3270
[charged_amount] => 20.2370
[total_discount] => 11.9400
[provinceName] => MB
[store_key] => 9
[store_id] => 1022
[categories] => Array
(
[2] => 0
[4] => 29.8500
[3] => 0
)
)
[2] => Array
(
[subtotal] => 0.3000
[taxes] => 0.0390
[charged_amount] => 0.3390
[total_discount] => 0.0000
[provinceName] => NB
[store_key] => 8
[store_id] => 1013
[categories] => Array
(
[2] => 0.3000
[4] => 0
[3] => 0
)
)
[3] => Array
(
[subtotal] => 24.3100
[taxes] => 1.1830
[charged_amount] => 10.2830
[total_discount] => 15.2100
[provinceName] => NL
[store_key] => 4
[store_id] => 3033
[categories] => Array
(
[2] => 24.3100
[4] => 0
[3] => 0
)
)
[4] => Array
(
[subtotal] => 1116.3400
[taxes] => 127.6960
[charged_amount] => 1110.0060
[total_discount] => 134.0300
[provinceName] => ON
[store_key] => 2
[store_id] => 1139
[categories] => Array
(
[2] => 85.7300
[4] => 143.2800
[3] => 887.3300
)
)
[5] => Array
(
[subtotal] => 10.8500
[taxes] => 1.4100
[charged_amount] => 12.2600
[total_discount] => 0.0000
[provinceName] => ON
[store_key] => 5
[store_id] => 1116
[categories] => Array
(
[2] => 10.8500
[4] => 0
[3] => 0
)
)
)
I just need to add the values of the array [categories] with same keys and use it further to print the total, but not getting correct output, can someone help me out to get the desired result:
Desired result
An array with same keys but total of individual array values
Array ( [2] => 0.9000 [4] => 29.8500 [3] => 1.5 )
NOTE: Initial array is dynamic can have n number of key value pair
Thanks
The first thing that you need to do is iterate through the outer array. Then, for each row in the outer array, you and to iterate through each entry in the category element. So this means that we have two foreach loops. Inside the inner foreach, we simply set the value for the current index to be the value of the same index on a 'sum' array (if it doesn't already exist), or increment the value of that index if it already exists in the 'sum' array.
<?php
$sumArray = array();
foreach($outerArray as $row)
{
foreach($row["categories"] as $index => $value)
{
$sumArray[$index] = (isset($sumArray[$index]) ? $sumArray[$index] + $value : $value);
}
}
?>
Demo using your example array
I have the following array:
Array
(
[0] => Array
(
[Import] => Array
(
[product_id] => 1
[id] => 1
[category_id] => 1
[amount] => 50
[cost] => 8320
[paid] => 0
[comment] => transportation and others cost: 100
[created] => 2015-06-22 12:09:20
)
[0] => Array
(
[total_sell] => 6
)
)
[1] => Array
(
[Import] => Array
(
[product_id] => 2
[id] => 2
[category_id] => 2
[amount] => 15
[cost] => 3000
[paid] => 0
[comment] =>
[created] => 2015-06-22 12:10:36
)
[0] => Array
(
[total_sell] => 1
)
)
[2] => Array
(
[Import] => Array
(
[product_id] => 1
[id] => 3
[category_id] => 1
[amount] => 15
[cost] => 2000
[paid] => 0
[comment] =>
[created] => 2015-06-22 12:10:58
)
[0] => Array
(
[total_sell] => 6
)
)
[3] => Array
(
[Import] => Array
(
[product_id] => 1
[id] => 4
[category_id] => 1
[amount] => 50
[cost] => 8000
[paid] => 0
[comment] =>
[created] => 2015-06-23 01:10:10
)
[0] => Array
(
[total_sell] => 6
)
)
)
I want to remove duplicate entry of [Import][product_id]. So my expected result is :
Array
(
[0] => Array
(
[Import] => Array
(
[product_id] => 1
[id] => 1
[category_id] => 1
[amount] => 50
[cost] => 8320
[paid] => 0
[comment] => transportation and others cost: 100
[created] => 2015-06-22 12:09:20
)
[0] => Array
(
[total_sell] => 6
)
)
[1] => Array
(
[Import] => Array
(
[product_id] => 2
[id] => 2
[category_id] => 2
[amount] => 15
[cost] => 3000
[paid] => 0
[comment] =>
[created] => 2015-06-22 12:10:36
)
[0] => Array
(
[total_sell] => 1
)
)
)
Would you write a function to filter this type of array and produce expected result. I have been googling for 2 days but no luck.
This is a handy one liner that should do the trick:
$unique= array_map("unserialize", array_unique(array_map("serialize", $original)));
If the underlying arrays are not identical, that won't work, in which case I think you could do:
$unique = array_intersect_key($original ,
array_unique(
array_map(function($item) {
return $item['Import']['product_id'];
}, $original)
)
);
Tested: http://sandbox.onlinephpfunctions.com/code/8aee5cbd614e0ddd1a03dfaa7e98c72fbbe7d68d
Here is a quick stable sort and reduce which runs in linearithmic time. First-encountered product Id's are kept, and entries with duplicate product Id's are ignored.
// Stable sort
sort($in);
// Reduce
$out = array_reduce($in, function(&$acc, &$item){
if($item['Import']['product_id'] !== #$acc[sizeof($acc)-1]['Import']['product_id']) {
$acc[] = $item;
}
return $acc;
}, []);
Demo: http://ideone.com/BP0eUJ
Update: Here is an even better linear-time algorithm that does the same as above using a fast "hash table" lookup. Again, the first-encountered product Id is kept and subsequent ones of the same Id are ignored.
$out = [];
$hashTable = [];
foreach($in as $item) {
$pid = $item['Import']['product_id'];
if(!isset($hashTable[$pid])) {
$out[] = $item;
$hashTable[$pid] = true;
}
}
Demo: http://ideone.com/5RF0og
I am trying to merge an array containing a multidimensional array using the value inside the multidimensional array called [color_id] key and combining the values inside the [details] key, Then, sort the values in the [model] key from least to greatest.
Here is the multidimensional array:
Array (
[0] => Array
(
[color_id] => 5
[details] => Array
(
[0] => Array
(
[quantity] => 1
[model] => 387110
[size] => small
)
[1] => Array
(
[quantity] => 1
[model] => 771410
[size] => medium
)
)
[1] => Array
(
[color_id] => 5
[details] => Array
(
[0] => Array
(
[quantity] => 1
[model] => 811110
[size] => medium
)
[1] => Array
(
[quantity] => 1
[model] => 958010
[size] => large
)
)
)
[2] => Array
(
[color_id] => 36
[details] => Array
(
[0] => Array
(
[quantity] => 1
[model] => 811310
[size] => small
)
[1] => Array
(
[quantity] => 1
[model] => 101901
[size] => large
)
)
)
[3] => Array
(
[color_id] => 36
[details] => Array
(
[0] => Array
(
[quantity] => 1
[model] => 387010
[size] => medium
)
[1] => Array
(
[quantity] => 2
[model] => 564310
[size] => medium
)
[2] => Array
(
[quantity] => 1
[model] => 864328
[size] => small
)
)
)
[4] => Array
(
[color_id] => 74
[details] => Array
(
[0] => Array
(
[quantity] => 1
[model] => 469871
[size] => large
)
[1] => Array
(
[quantity] => 2
[model] => 368599
[size] => medium
)
[2] => Array
(
[quantity] => 1
[model] => 785958
[size] => small
)
)
)
[5] => Array
(
[color_id] => 74
[details] => Array
(
[0] => Array
(
[quantity] => 1
[model] => 958741
[size] => small
)
[1] => Array
(
[quantity] => 2
[model] => 123688
[size] => medium
)
)
)
)
I'm trying to get this result without any luck.
Array (
[0] => Array
(
[color_id] => 5
[details] => Array
(
[0] => Array
(
[quantity] => 1
[model] => 387110
[size] => small
)
[1] => Array
(
[quantity] => 1
[model] => 771410
[size] => medium
)
[3] => Array
(
[quantity] => 1
[model] => 811110
[size] => medium
)
[4] => Array
(
[quantity] => 1
[model] => 958010
[size] => large
)
)
[1] => Array
(
[color_id] => 36
[details] => Array
(
[0] => Array
(
[quantity] => 1
[model] => 101901
[size] => large
)
[1] => Array
(
[quantity] => 1
[model] => 387010
[size] => medium
)
[3] => Array
(
[quantity] => 2
[model] => 564310
[size] => medium
)
[4] => Array
(
[quantity] => 1
[model] => 811310
[size] => small
)
[5] => Array
(
[quantity] => 1
[model] => 864328
[size] => small
)
)
)
[2] => Array
(
[color_id] => 74
[details] => Array
(
[0] => Array
(
[quantity] => 2
[model] => 123688
[size] => medium
)
[1] => Array
(
[quantity] => 2
[model] => 368599
[size] => medium
)
[2] => Array
(
[quantity] => 1
[model] => 469871
[size] => large
)
[3] => Array
(
[quantity] => 1
[model] => 785958
[size] => small
)
[4] => Array
(
[quantity] => 1
[model] => 958741
[size] => small
)
)
)
)
Greatly appreciate the help. Thank you.
I would do it like this (expecting your array as $array):
// output array
$newArray = array();
// loop through the $array
for($i=0; $i<count($array); $i++) {
// check if this is the first iteration
if($i == 0) {
// if so, push the first element into the new array
array_push($newArray,$array[$i]);
// and continue with the next iteration
continue;
}
// found flag for the color_id key
$found = false;
// loop through the new array to check if the color_id is in there yet
foreach($newArray as &$subArr) {
// check if there is the color id of the current iteration (of the for loop)
if($subArr['color_id'] == $array[$i]['color_id']) {
// if it is, push all the details in this color_id, flag as found and break out
foreach($array[$i]['details'] as $details) array_push($subArr['details'],$details);
$found = true;
break;
}
}
// check if the color_id was found
if(!$found) {
// if not, push the current color_id into the new array
array_push($newArray,$array[$i]);
}
}
// loop through the new array
foreach($newArray as &$newSubArray) {
// sort by model
uasort($newSubArray['details'], function($a,$b){return $a['model']-$b['model'];});
}
By the way: is it necessary to save the color_name in this array? Because it is redundant ;)
Ok so here is my first array:
(
[1] => Array
(
[27] => Array
(
[product_id] => 27
[type] => hardware
[step_number] => 1
)
[372] => Array
(
[product_id] => 372
[type] => hardware
[step_number] => 1
)
[92] => Array
(
[product_id] => 92
[type] => hardware
[step_number] => 1
)
)
[2] => Array
(
[335] => Array
(
[product_id] => 335
[type] => hardware
[step_number] => 2
)
[62] => Array
(
[product_id] => 62
[type] => hardware
[step_number] => 2
)
[356] => Array
(
[product_id] => 356
[type] => hardware
[step_number] => 2
)
)
and here is my second array
(
[1] => Array
(
[655] => Array
(
[product_id] => 655
[type] => optional
[step_number] => 1
)
[54] => Array
(
[product_id] => 54
[type] => optional
[step_number] => 1
)
[554] => Array
(
[product_id] => 554
[type] => optional
[step_number] => 1
)
)
[2] => Array
(
[33] => Array
(
[product_id] => 33
[type] => optional
[step_number] => 2
)
[612] => Array
(
[product_id] => 612
[type] => optional
[step_number] => 2
)
[5] => Array
(
[product_id] => 5
[type] => optional
[step_number] => 2
)
)
[3] => Array
(
[444] => Array
(
[product_id] => 444
[type] => optional
[step_number] => 3
)
[6] => Array
(
[product_id] => 6
[type] => optional
[step_number] => 3
)
[53] => Array
(
[product_id] => 53
[type] => optional
[step_number] => 3
)
)
Basically what i need is the second array appended to the end of the first array with the keys of the first array preserved the keys and changing the step_number to the new key so the final keys looks like
(
[1] => Array
(
[27] => Array
(
[step_number] => 1)
....
[2] => Array
(
[335] => Array
(
[step_number] => 2)
....
[3] => Array
(
[655] => Array
(
[step_number] => 3)
....
[4] => Array
(
[33] => Array
(
[step_number] => 4)
....
[5] => Array
(
[444] => Array
(
[step_number] => 5)
....
but when i do
$all = array_merge($first, $second);
the keys are
(
[0] => Array
[1] => Array
[2] => Array
[3] => Array
[4] => Array
Is that possible to do....
Try array_merge_recursive .. http://php.net/array_merge_recursive
This is also from the manual on array_splice if you're just looking to append your 2nd array onto the first (http://php.net/manual/en/function.array-push.php):
array_splice($first, count($first), 0, $second);
Iterating over the first set of keys, then using the Union array operator should do the trick.
//$first = array(...);
//$second = array(...);
foreach ($second as $key => $value)
{
if (!isset($first[$key]))
{
$first[$key] = array();
}
$first[$key] += $value;
}