Mad Adh Mad Adh - 5 months ago 13
PHP Question

How can I group a multidimensional array by a specific key of its inner arrays?

I have an array like this:

$my_array = array(
array(
array('cnt' => 1, 'date' => '2016-06-18', 'name' => 'Phone Calls'),
array('cnt' => 1,'date' => '2016-06-18','name' => 'Others Works')
),
array(
array('cnt' => 2 , 'date' => '2016-06-17', 'name' => 'Phone Calls'),
array('cnt' => 1, 'date' => '2016-06-17', 'name' => 'Others Works')
)
);


which I need to convert into the format below to accomplish my specific purpose.

$desired_result = array(
array('name' => 'Phone Calls', 'dateDetail' => array(
array('cnt' => 1, 'date' => '2016-06-18'),
array('cnt' => 2, 'date' => '2016-06-17'),
)),
array('name' => 'Others Works', 'dateDetail' => array(
array('cnt' => 1, 'date' => '2016-06-18'),
array('cnt' => 1, 'date' => '2016-06-17'),
))
);


I need to group my array by name with all date and count data together inside. Can someone please help me to format this array?

Answer

You can group by name by popping off the name from each of the lowest level arrays and using it as a higher-level key for the reorganized array.

foreach ($your_array as $day) {
    foreach ($day as $item) {
        $name = array_pop($item);                  // removes the 'name' key and returns it
        $converted[$name]['name'] = $name;
        $converted[$name]['dateDetail'][] = $item;
    }
}

$result = array_values($converted);                // convert from string keys to numeric

array_pop only happens to work because name is the last key in the item arrays. If it wasn't, you would need to specify which key to remove and use like this:

$name = $item['name'];
unset($item['name']);

To add grouping by date within the dateDetail array for each name, the idea is the same as when grouping by name. Use date as a key within dateDetail, and add to the cnt key for repeated date values.

foreach ($your_array as $day) {
    foreach ($day as $item) {
        $name = array_pop($item);
        $new[$name]['name'] = $name;

        // check if the date is already set
        if (isset($new[$name]['dateDetail'][$item['date']])) {
            // if so, add the count of the current item
            $new[$name]['dateDetail'][$item['date']]['cnt'] += $item['cnt'];
        } else {
            // if not, set it.
            $new[$name]['dateDetail'][$item['date']] = $item;
        }
    }
}

// remove the date string keys
foreach ($new as &$name) {
    $name['dateDetail'] = array_values($name['dateDetail']);
}
unset($name);    // unset the reference

// remove the name string keys
$result = array_values($new);
Comments