Manolis
Manolis

Reputation: 891

Group data from a 2d array by one column then conditionally populate keys within the group and count the number of subarray key occurrences

I have the following array

$topics_percentage = [
    ['id' => 8989, 'cat' => 'Category 1', 'completed' => 0],
    ['id' => 8919, 'cat' => 'Category 2', 'completed' => 1],
    ['id' => 8913, 'cat' => 'Category 2', 'completed' => 1],
    ['id' => 8947, 'cat' => 'Category 1', 'completed' => 1],
    ['id' => 8949, 'cat' => 'Category 3', 'completed' => 1],
];

I need to group by category values as the first level keys, then conditionally count the completed and noncompleted values in each group according to the 0 or 1 value of the completed elements.

Desired result:

[
    'Category 1' => [
        'noncompleted' => 1,
        'completed' => 1,
    ],
    'Category 2' => [
        'completed' => 2,
    ],
    'Category 3' => [
        'completed' => 1,
    ]
]

Upvotes: -1

Views: 505

Answers (3)

mickmackusa
mickmackusa

Reputation: 47874

Use array destructuring to only access needed values from each row and declare them as convenient variables.

Use the cat values as first level keys.

Use a lookup array to determine the second level key.

While iterating, add the current value to the previously stored value (or zero if it is the first encounter).

Code: (Demo)

$result = [];
$lookup = ['noncompleted', 'completed'];
foreach ($topics_percentage as ['cat' => $cat, 'completed' => $comp]) {
    $result[$cat][$lookup[$comp]] = ($result[$cat][$lookup[$comp]] ?? 0) + 1;
}
var_export($result);

Upvotes: 1

ty812
ty812

Reputation: 3323

Try this:

    foreach ($topics_percentage as $v) {

        $complete = $v['completed'];

        if ($complete == 1) {
            $class_array[$v['cat']]['completed']++;
        } else {
            $class_array[$v['cat']]['uncompleted']++;
        }
    }

You should, of course, preinitialize the array before you count up values, but the basic idea is to use array cells as numeric values to be added or substracted from.

Upvotes: 0

hindmost
hindmost

Reputation: 7195

Try this:

$values = array_unique(array_map(
    function ($v) { return $v['cat']; },
    $array
));

$result = array();
foreach ($values as $val) {
    $flt = array_filter($array, function ($v) use ($val) {
        return $v['cat'] == $val;
    });
    $cnt = count(array_filter($array, function ($v) use ($val) {
        return $v['completed'];
    }));
    $result[$val] = array(
        'completed' => $cnt,
        'noncompleted' => count($flt) - $cnt
    );
}

Upvotes: 1

Related Questions