开发者

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));
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜