开发者

Group 2d array rows by one column and sum another column [duplicate]

This question already has answers here: Group array data on one column and sum data from another column (5 answers) Closed 5 months ago.

I have a php array like this:

[
    ['url_id' => 2191238, 'time_spent' => 41],
    ['url_id' => 2191606, 'time_spent' => 215],
    ['url_id' => 2191606, 'time_spent' => 25]
]

How开发者_如何学Go to get the SUM of time_spent based on group by url_id (using array_count_values?)?


Let's pretend that $array contains our data. We will go through the array and continually add the time_spent to another array keyed by url_id.

$ts_by_url = array();
foreach($array as $data) {
    if(!array_key_exists($data['url_id'], $ts_by_url))
        $ts_by_url[ $data['url_id'] ] = 0;
    $ts_by_url[ $data['url_id'] ] += $data['time_spent'];
}

$ts_by_url should now contain:

2191238 => 41
2191606 => 240 // == 215 + 25


The OP posted an interesting problem, but the suggestion of using array_count_values() was not applicable; the function does not sum array values but counts their frequency. The answer of @marcocassisa works but is insufficient because of the unfortunate emission of E_NOTICES, albeit unrelated to any math issue. (An undefined variable is unset and thus of NULL value, but in a math context it will temporarily be coerced into a value of zero.) Modern PHP discourages the use of undefined variables by intentionally raising notices when code utilizes them, with one exception starting with PHP 5.1: a statement consisting of only an undefined variable; see here.

To rectify the aforementioned solution, one might use two foreach loops, one to set the index keys and initialize the array elements while the other would perform the summing of values, as follows:

<?php

// set keys and initialize
foreach($arr as $data) {
    $its_by_url[ $data["url_id"] ] = 0;
} 

// now can sum values by url id number:
foreach($arr as $data) {
    $its_by_url[ $data["url_id"] ] += $data["time_spent"];
}

see demo.

While satisfactory, this solution lacks elegance. Attempting to combine the two foreach loops into one, will negatively impact the second element, as it gets defined and then needlessly redefined. One could code per the answer of @Charles and create the url id numbered index if it doesn't already exist. Or, you could test to see if it is set, as follows:

<?php
foreach($arr as $data) {
   if ( !isset( $its_by_url[ $data["url_id"] ] ) ) {
             $its_by_url[ $data["url_id"] ] = 0;
   }
   $its_by_url[ $data["url_id"] ] += $data["time_spent"]; 
}

see demo

Note: if an array element were defined as null, then isset() would return false while array_key_exists() would return true. Per, Ilia Alshanetsky

... if your application does not need to distinguish between an array key that does not exist and one whose value happens to be NULL you should use isset() because it happens to be a little faster.


Why not a simpler

$ts_by_url = array();
foreach($array as $data) {
    $ts_by_url[ $data['url_id'] ] += $data['time_spent'];
}
0

上一篇:

下一篇:

精彩评论

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

最新问答

问答排行榜