GivP
GivP

Reputation: 2654

Group rows in a 2d array and count number of rows in each respective group

I have an array of 200 items. I would like to output the array but group the items with a common value. Similar to SQL's GROUP BY method. This should be relatively easy to do but I also need a count for the group items.

Does anyone have an efficient way of doing this? This will happen on every page load so I need it to be fast and scalable.

Could I perhaps dump the results into something like Lucene or SQLite then run a query on that document on each page load?

Upvotes: 13

Views: 38070

Answers (5)

mickmackusa
mickmackusa

Reputation: 47992

Without sample data (a minimal, clear verifiable example) in the question it is difficult to confidently give precise advice on the best way(s) to perform the task. One way is to use temporary grouping keys in the result array. Store an encountered whole row and an appended count element in the result array if the identifying key hadn't been encountered before. The appended element should have a value of 0. Then unconditionally increment the count value. When the loop is finished, if you don't want the grouping keys, you can call array_values().

Code: (Demo)

$result = [];
foreach ($array as $row) {
    $result[$row['group']] ??= $row + ['count' => 0]; // only save 1st of group with 0 count
    ++$result[$row['group']]['count']; // increment the count
}
var_export(array_values($result));

Upvotes: 0

SuperDude
SuperDude

Reputation: 1

"$Switches" Array with [3] elements
0       
    SwitchID    1   
    name    k�  
    type    output  
    displayAs   button  
    value   on  
    groupname   group1  
1   Array [6]   
2   Array [6]   


// this will sort after groupname

$result = array();
$target = count($Switches);
for($i=0;$i<$target;$i++)
{
    $groupname = $Switches[$i]["groupname"];

    $result[$groupname][] = $Switches[$i];
}

// count amount of groups
$groupCount = count($result);

... or did i miss something?

Upvotes: -1

Marcos Nakamine
Marcos Nakamine

Reputation: 1436

$aA = array_count_values(array(1,2,3,4,5,1,2,3,4,5,6,1,1,1,2,2));
$aB = array();
foreach($aA as $index=>$aux){
     array_push($aB,$index);
}
print_r($aB);

Result:

Array ( [0] => 1 [1] => 2 [2] => 3 [3] => 4 [4] => 5 [5] => 6 ) 

Upvotes: 2

Ferdinand Beyer
Ferdinand Beyer

Reputation: 67177

Just iterate over the array and use another array for the groups. It should be fast enough and is probably faster than the overhead involved when using sqlite or similar.

$groups = array();
foreach ($data as $item) {
    $key = $item['key_to_group'];
    if (!isset($groups[$key])) {
        $groups[$key] = array(
            'items' => array($item),
            'count' => 1,
        );
    } else {
        $groups[$key]['items'][] = $item;
        $groups[$key]['count'] += 1;
    }
}

Upvotes: 30

chaos
chaos

Reputation: 124325

$groups = array();
foreach($items as $item)
    $groups[$item['value']][] = $item;
foreach($groups as $value => $items)
    echo 'Group ' . $value . ' has ' . count($items) . ' ' . (count($items) == 1 ? 'item' : 'items') . "\n";

Upvotes: 14

Related Questions