Reputation: 521
I have an array with dynamic values. The goal is to merge the subarrays
which have same code
and sum of cost
value with same code
.
$array = [
[
['code'=>'AA', 'name'=>'A Name', 'cost'=>'10'],
['code'=>'AB', 'name'=>'B Name', 'cost'=>'15'],
],
[
['code'=>'AA', 'name'=>'A Name', 'cost'=>'15'],
['code'=>'AB', 'name'=>'B Name', 'cost'=>'10'],
['code'=>'AC', 'name'=>'C Name', 'cost'=>'10'],
],
[
['code'=>'AA', 'name'=>'A Name', 'cost'=>'5'],
['code'=>'AB', 'name'=>'B Name', 'cost'=>'10'],
['code'=>'AC', 'name'=>'C Name', 'cost'=>'15'],
]
];
Desired result:
[
[
['code'=>'AA', 'name'=>'A Name', 'cost'=>'30'],
['code'=>'AB', 'name'=>'B Name', 'cost'=>'35'],
]
]
The result is only code AA and BB because code AC not exist on first index. Then cost values within each group are summed.
Upvotes: 0
Views: 75
Reputation: 36
$array = array(
array(
array(
'code'=>'AA',
'name'=>'A Name',
'cost'=>'10',
),
array(
'code'=>'AB',
'name'=>'B Name',
'cost'=>'15',
),
),
array(
array(
'code'=>'AA',
'name'=>'A Name',
'cost'=>'15',
),
array(
'code'=>'AB',
'name'=>'B Name',
'cost'=>'10',
),
array(
'code'=>'AC',
'name'=>'C Name',
'cost'=>'10',
),
),
array(
array(
'code'=>'AA',
'name'=>'A Name',
'cost'=>'5',
),
array(
'code'=>'AB',
'name'=>'B Name',
'cost'=>'10',
),
array(
'code'=>'AC',
'name'=>'C Name',
'cost'=>'15',
),
),
);
$the_biggest_number=count($array);
$new_array = array();
foreach ($array as $key => $val) {
foreach ($val as $sub_key => $sub_val) {
if(!isset($new_array[$sub_val['code']])){
$sub_val['count']=1;
$new_array[$sub_val['code']]=$sub_val;
}
else{
$new_array[$sub_val['code']]['cost'] += $sub_val['cost'];
$new_array[$sub_val['code']]['count'] += 1;
}
}
}
$result=array();
foreach ($new_array as $key => $val) {
if($val['count']==$the_biggest_number){
unset($val['count']);
$result[]=$val;
}
}
$result= array($result);
echo '<pre>';
print_r($result);
Upvotes: 2
Reputation: 432
UPDATED
<?php
$collection = array(
array(
array(
'code'=>'AA',
'name'=>'A Name',
'cost'=>'10',
),
array(
'code'=>'AB',
'name'=>'B Name',
'cost'=>'15',
),
array(
'code'=>'AD',
'name'=>'D Name',
'cost'=>'45',
),
),
array(
array(
'code'=>'AA',
'name'=>'A Name',
'cost'=>'15',
),
array(
'code'=>'AB',
'name'=>'B Name',
'cost'=>'10',
),
array(
'code'=>'AC',
'name'=>'C Name',
'cost'=>'10',
),
),
array(
array(
'code'=>'AA',
'name'=>'A Name',
'cost'=>'5',
),
array(
'code'=>'AB',
'name'=>'B Name',
'cost'=>'10',
),
array(
'code'=>'AC',
'name'=>'C Name',
'cost'=>'15',
),
),
);
$newcollection=array();
$keysregistered=array();
$i=1;
foreach($collection as $list) {
$collectionkeys = array();
foreach($list as $arr) {
$key=$arr['code'];
$collectionkeys[]=$key;
if(isset($keysregistered[$key])) {
$oldtotal = $keysregistered[$key];
$total = $oldtotal+$arr['cost'];
$newcollection[$key]['cost'] = $total;
} else {
if($i==1) {
$newcollection[$key] = $arr;
$keysregistered[$key] = $arr['cost'];
}
}
}
$registeredkeys = array_keys($keysregistered);
$diff = array_diff($registeredkeys,$collectionkeys);
foreach($diff as $delkey) {
unset($keysregistered[$delkey],$newcollection[$delkey]);
}
$i++;
}
$finalarr = array_values($newcollection);
print_r($finalarr);
?>
Now code is updated, it will even remove AD from the first item and give you totals for unique codes.
Upvotes: 0
Reputation: 16997
Its simple, here is a way
<?php
$codes = array_column($array[0],"code");
$out =array();
foreach($array as $main)
{
foreach($main as $sub)
{
if(in_array($sub['code'], $codes))
{
if(isset($out[$sub['code']]))
{
$out[$sub['code']]['cost']+=$sub['cost'];
}else
{
$out[$sub['code']] = $sub;
}
}
}
}
print_r(array_values($out));
?>
Test Results
akshay@db-3325:/tmp$ cat test.php
<?php
$array = array(
array(
array(
'code'=>'AA',
'name'=>'A Name',
'cost'=>'10',
),
array(
'code'=>'AB',
'name'=>'B Name',
'cost'=>'15',
),
),
array(
array(
'code'=>'AA',
'name'=>'A Name',
'cost'=>'15',
),
array(
'code'=>'AB',
'name'=>'B Name',
'cost'=>'10',
),
array(
'code'=>'AC',
'name'=>'C Name',
'cost'=>'10',
),
),
array(
array(
'code'=>'AA',
'name'=>'A Name',
'cost'=>'5',
),
array(
'code'=>'AB',
'name'=>'B Name',
'cost'=>'10',
),
array(
'code'=>'AC',
'name'=>'C Name',
'cost'=>'15',
),
),
);
$codes = array_column($array[0],"code");
$out =array();
foreach($array as $main)
{
foreach($main as $sub)
{
if(in_array($sub['code'], $codes))
{
if(isset($out[$sub['code']]))
{
$out[$sub['code']]['cost']+=$sub['cost'];
}else
{
$out[$sub['code']] = $sub;
}
}
}
}
print_r(array_values($out));
?>
Output
akshay@db-3325:/tmp$ php test.php
Array
(
[0] => Array
(
[code] => AA
[name] => A Name
[cost] => 30
)
[1] => Array
(
[code] => AB
[name] => B Name
[cost] => 35
)
)
Upvotes: 1
Reputation: 92904
The solution using array_column
, array_map
, call_user_func_array
and array_merge
functions:
// $arr is your initial array
$merged = call_user_func_array("array_merge", $arr);
// getting `code` keys from the first nested item
$result = array_map(function($v){
return [];
}, array_column($arr[0], 'cost', 'code'));
foreach ($merged as $item) {
if (isset($result[$item['code']])) {
if ($result[$item['code']]) {
$result[$item['code']]['cost'] += $item['cost'];
} else {
$result[$item['code']] = $item;
}
}
}
$result = [array_values($result)];
print_r($result);
The output:
Array
(
[0] => Array
(
[0] => Array
(
[code] => AA
[name] => A Name
[cost] => 30
)
[1] => Array
(
[code] => AB
[name] => B Name
[cost] => 35
)
)
)
Upvotes: 0
Reputation: 15141
<?php
ini_set("display_errors", 1);
$array = array(
array(
array(
'code'=>'AA',
'name'=>'A Name',
'cost'=>'10',
),
array(
'code'=>'AB',
'name'=>'B Name',
'cost'=>'15',
),
),
array(
array(
'code'=>'AA',
'name'=>'A Name',
'cost'=>'15',
),
array(
'code'=>'AB',
'name'=>'B Name',
'cost'=>'10',
),
array(
'code'=>'AC',
'name'=>'C Name',
'cost'=>'10',
),
),
array(
array(
'code'=>'AA',
'name'=>'A Name',
'cost'=>'5',
),
array(
'code'=>'AB',
'name'=>'B Name',
'cost'=>'10',
),
array(
'code'=>'AC',
'name'=>'C Name',
'cost'=>'15',
),
),
);
$newData=array();
array_map(function($arrayData) use(&$newData){
foreach($arrayData as $data => $value)
{
$newData[]=$value;
}
}, $array);
$result=array();
array_map(function($data) use(&$result){
// array("AA","AB") in this array you can add your code for which you want to merge.
if(in_array($data["code"], array("AA","AB")))
{
if(!isset($result[$data["code"]]))
{
$result[$data["code"]]=$data;
}
else
{
$result[$data["code"]]["cost"]+=$data["cost"];
}
}
}, $newData);
$result=array(array_values($result));
print_r($result);
Output:
Array
(
[0] => Array
(
[0] => Array
(
[code] => AA
[name] => A Name
[cost] => 30
)
[1] => Array
(
[code] => AB
[name] => B Name
[cost] => 35
)
)
)
Upvotes: 0