可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I have the following array, in which I want to sum up the total_volume for all entries where the source and the target are the same.
Array (
[0] => Array
(
[source] => ABC
[target] => DEF
[total_volume] => 10
)
[1] => Array
(
[source] => ABC
[target] => GHI
[total_volume] => 5
)
[2] => Array
(
[source] => ABC
[target] => DEF
[total_volume] => 5
)
)
The resulting array should look like this:
ResultArray (
[0] => Array
(
[source] => ABC
[target] => DEF
[total_volume] => 15
)
[1] => Array
(
[source] => ABC
[target] => GHI
[total_volume] => 5
)
)
My first thought would be to llop through the existing array and check via a nested loop over the ResultArray whether an entry with the matching source-target-pair already exists.
Is there an other way using array_walk() or a similar method?
Thanks in advance for your help!
回答1:
not pretty but heres how I would do it with a nested foreach;
$aStartingArray = array();
$aStartingArray[] = array('source'=>'ABC', 'target' => 'DEF', 'total_volume' => 10);
$aStartingArray[] = array('source'=>'ABC', 'target' => 'GHI', 'total_volume' => 5);
$aStartingArray[] = array('source'=>'ABC', 'target' => 'DEF', 'total_volume' => 5);
$aSortedArray = array();
foreach ($aStartingArray as $aArray) {
$bSet = false;
foreach ($aSortedArray as $iPos => $aTempSortedArray) {
if(
$aTempSortedArray['source'] == $aArray['source'] &&
$aTempSortedArray['target'] == $aArray['target']){
$aSortedArray[$iPos]['total_volume'] += $aArray['total_volume'];
$bSet = true;
}
}
if(!$bSet) {
$aSortedArray[] = array(
'source' => $aArray['source'],
'target' => $aArray['target'],
'total_volume' => $aArray['total_volume']
);
}
}
var_dump($aSortedArray);
回答2:
This is a fast try (sorry, it uses twice array_walk)
<?php
$a = [
['source' => 'ABC', 'target' => 'DEF', 'total_volume' => 10 ],
['source' => 'ABC', 'target' => 'GHI', 'total_volume' => 5 ],
['source' => 'ABC', 'target' => 'DEF', 'total_volume' => 5 ],
];
$tmp = [];
array_walk($a, function (&$item, $key) use (&$tmp) {
$resKey = $item['source'].'_'.$item['target'];
if (!isset($result[$resKey])) {
$result[$resKey] = 0;
}
$tmp[$resKey] += $item['total_volume'];
});
$result = [];
array_walk($tmp, function (&$item, $key) use (&$result) {
list ($source, $target) = explode('_', $key);
$result[] = ['source' => $source, 'target' => $target, 'total_volume' => $item];
});
var_dump($result);
回答3:
How about this? A bit briefer I think.
$a = [
['source' => 'ABC', 'target' => 'DEF', 'total_volume' => 10 ],
['source' => 'ABC', 'target' => 'GHI', 'total_volume' => 5 ],
['source' => 'ABC', 'target' => 'DEF', 'total_volume' => 5 ],
];
$result = $result2 = [];
array_walk($a, function(&$item, $key) use(&$result) {
if(! isset($result[$item['source']]))
$result[$item['source']] = [];
if(! isset($result[$item['source']][$item['target']]))
$result[$item['source']][$item['target']] = 0;
$result[$item['source']][$item['target']] += $item['total_volume'];
});
foreach($result as $key => $val) {
foreach($val as $k => $v) {
$result2[] = [$key,$k,$v];
}
}
print_r($result2);
回答4:
Another alternative. Not best but will work.
$arr = [
['source' => 'ABC', 'target' => 'DEF', 'total_volume' => 10 ],
['source' => 'ABC', 'target' => 'GHI', 'total_volume' => 5 ],
['source' => 'ABC', 'target' => 'DEF', 'total_volume' => 5 ],
];
$res = $resulrArr = [];
foreach($arr as $record){
$record = array_values($record);
$res[$record[0].'_'.$record[1]] = !empty($res[$record[0].'_'.$record[1]]) ? $res[$record[0].'_'.$record[1]] + $record[2] : $record[2];
}
$resulrArr = array_map(function($v,$k){
$data = explode('_',$k);
$resulrArr['source'] = $data[0];
$resulrArr['target'] = $data[1];
$resulrArr['total_volume'] = $v;
return $resulrArr;
},$res,array_keys($res));
echo '<pre>'; print_r($resulrArr);