Collating multidimensional array values
I have a multidimensional array in the form of;
Array
(
[0] => Array
(
[DATE] => 05-19-2011
[PERSON] => Bob Hope
[ITEM] => Holiday
[DURATION] => 04:00
)
[1] => Array
(
[DATE] => 05-19-2011
[PERSON] => Bob Hope
[ITEM] => Work
[DURATION] => 05:00
)
[2] => Array
(
[DATE] => 05-19-2011
[PERSON] => Bob Hope
[ITEM] => Holiday
[DURATION] => 06:00
)
[3] => Array
(
[DATE] => 05-19-2011
[PERSON] => Bob Hope
[ITEM] => Work
[DURATION] => 05:00
)
[4] => Array
(
[DATE] => 05-19-2011
[PERSON] => Joe Bloggs
[ITEM] => Holiday
[DURATION] => 02:00
)
[5] => Array
(
[DATE] => 05-19-2011
[PERSON] => Joe Bloggs
[ITEM] => Work
[DURATION] => 03:00
)
[6] => Array
(
[DATE] => 05-19-2011
[PERSON] => Joe Bloggs
[ITEM] => Holiday
[DURATION] => 03:00
)
[7] => Array
(
[DATE] => 05-19-2011
[PERSON] => Joe Bloggs
[ITEM] => Work
[DURATION] => 02:00
)
)
And want to collate the results, totalling the holiday and work for each person so that I can output something in the form of;
Array
(
[0] => Array
(
[DATE] => 05-19-2011
[PERSON] => Bob Hope
[ITEM] => Holiday
[DURATION] => 10:00
)
[1] => Array
(
[DATE] => 05-19-2011
[PERSON] => Bob Hope
[ITEM] => Work
[DURATION] => 10:00
)
[2] => Array
(
[DATE] => 05-19-2011
[PERSON] => Joe Bloggs
[ITEM] => Holiday
[DURATION] => 05:00
)
[3] => Array
(
[DATE] => 05-19-2011
[PERSON] => Joe B开发者_运维技巧loggs
[ITEM] => Work
[DURATION] => 05:00
)
)
Any ideas? Any and all help appreciated.
Where's the data coming from? Generally, such data comes from a database, in which case the following statement would do exactly what you want:
SELECT
SUM(DURATION),
ITEM,
PERSON
FROM
yourtable
GROUP BY
PERSON,
ITEM;
Edit: If you want to group them by items too, just declare that.
Well, a lot of foreach's, but you are basically adding the values in a separate structure, and rearrange the resulting array:
$items = array(
0 => Array(
'DATE' => '05-19-2011',
'PERSON' => 'Bob Hope',
'ITEM' => 'Holiday',
'DURATION' => '10:00',
),
1 => Array(
'DATE' => '05-19-2011',
'PERSON' => 'Bob Hope',
'ITEM' => 'Work',
'DURATION' => '10:00',
),
2 => Array(
'DATE' => '05-19-2011',
'PERSON' => 'Joe Bloggs',
'ITEM' => 'Holiday',
'DURATION' => '05:00',
),
3 => Array(
'DATE' => '05-19-2011',
'PERSON' => 'Joe Bloggs',
'ITEM' => 'Work',
'DURATION' => '05:00',
),
);
foreach($items as $key=>$value){
$item = $value['ITEM'];
$out[$value['PERSON']][$value['DATE']][$value['ITEM']] += $value['DURATION'];
}
foreach($out as $person=>$data){
foreach($data as $date=>$items){
foreach($items as $item=>$duration){
$result[] = array(
'PERSON'=>$person,
'DATE'=>$date,
'ITEM'=>$item,
'DURATION'=>$duration,
);
}
}
}
print_r($result);
- Declare a new array.
- Iterate over the old array
- If the new array is empty, add the current array element to it
- If not, iterate over the new array
- if none of the new array's elements match the current array element, add it
- else add the current element's DURATION to the relevant new array's element
If you really want to solve this with PHP i would recommend to not nest too many loops. Here is my solution (which looks quite ugly btw.):
$result = array();
foreach ($data as $row) {
$key = $row['PERSON'] . '|' . $row['ITEM'];
$tmp = explode(':', $row['DURATION']);
$row['DURATION'] = $tmp[0] * 60 + $tmp[1];
if (!isset($result[$key])) {
$result[$key] = $row;
} else {
$result[$key]['DURATION'] += $row['DURATION'];
}
}
$result = array_map(function($v) {
$v['DURATION'] = strftime('%M:%S', $v['DURATION']);
return $v;
}, array_values($result));
精彩评论