php - Get level-specific element counts from a multidimensional array

538

I'm trying to determine the count of each array within a multidimensional associative array. For example, if I have an array like:

array(
    'food' => array(
        'soup' => array(
            'chicken noodle' => 
            'tomato' => 
            'french onion' => 
        ),

        'salad' => array(
            'house' => 
            'ceasar' =>
        ),
    ),
    'drink' => array(
        'soda' => array(
            'coke' => 
            'sprite' => 
            'dr pepper' => 
        ),

        'alcoholic' => array(
            'whiskey' => array(
                'Jim Beam' => 
                'Jameson' =>
                'Bushmills' =>
            ),
            'vodka' => array(
                'Stolichnaya' => 
                'Ketel One' =>
                'Grey Goose' =>
                'Belvedere' =>
            ),
            'rum' => array(
                'Captain Morgan' => 
                'Bacardi' =>
            ),
        ),
    ),
)

Not too sure how to explain this so I'll do my best. I want to find out the count of each array inside the array. So the values I'd expect from this array would look something like:

array(
        // total count of all arrays at  "level 1" (i.e. food & drink)
        0 => 2,
        // total count of all arrays at  "level 2" (i.e. soup, salad, soda, alcoholic)
        1 => 4,
        // total count of all arrays at  "level 3" (i.e. chicken noodle, tomato, french onion, house, ceasar, coke, sprite, dr pepper, whiskey, vodka, rum)
        2 => 11,
        // total count of all arrays at  "level 4" (i.e. Jim Beam, Jameson, Bushmills, Stolichnaya, Ketel One, Grey Goose, Belvedere, Captain Morgan, Bacardi)
        3 => 9
)

Now I'm aware that I'm only using the index keys for the values as opposed to the values, and while it would be easier to get these values if the array was a standard indexed array (I think I'm using correct terminology here, feel free to correct me- the whole point of course is for me to understand here- not for someone to just "give me an answer" :)) since I could then just loop through the array in afor($i = 0 $i < count($array); $i++) loop and increment my counts accordingly. I've searched SO for such an issue but haven't found it, if I missed it though feel free to simply point me to it. Thanks!

264

Answer

Solution:

Basically, use a recursive function (countLevels in the example below) that goes through every level of the array, counting each index that is an array, and adds that count to a master "counting" array ($levels).$levels is passed by reference, and the count of each level is updated directly on it. You can stick this right into your class, as I did below.

Below is what I think you want your class to look like. If you want$data to be a member of the class, declare the variable withvar $data and fill it inside the constructor.

class Test {
    public function getCounts($data) {
        $counts = array();
        $this->countLevels($counts, 0, $data);
        return $counts;
    }

    // Counts the number of arrays in each level of $data
    private function countLevels(&$levels, $current, $parent) {
        if (! isset($levels[$current])) {
            $levels[$current] = 0;
        }
        foreach ($parent as $child) {
            $levels[$current]++;
            if (is_array($child)) {
                $this->countLevels($levels, $current+1, $child);
            }
        }
        return $levels;
    }
}

// Let's use the class! Create an instance of it
$test = new Test();

// Fill the data array
$data = [
    'food' => [
        'soup' => [
            'chicken_noodle' => '',
            'tomato' => '',
            'french onion' => '',
        ],
        'salad' => [
            'house' => '',
            'ceasar' => '',
        ],
    ],
    'drink' => [
        'soda' => [
            'coke' => '',
            'sprite' => '',
            'dr pepper' => '',
        ],
        'alcoholic' => [
            'whiskey' => [
                'Jim Beam' => '',
                'Jameson' => '',
                'Bushmills' => '',
            ],
            'vodka' => [
                'Stolichnaya' => '',
                'Ketel One' => '',
                'Grey Goose' => '',
                'Belvedere' => '',
            ],
            'rum' => [
                'Captain Morgan' => '',
                'Bacardi' => '',
            ],
        ],
    ],
];

// Count the data for arrays on each level
$counts = $test->getCounts($data);

// Print the results
var_export($counts);

Output:

array (
  0 => 2,
  1 => 4,
  2 => 11,
  3 => 9,
)

People are also looking for solutions to the problem: php - Show token username symfony2 in twig

Source

Didn't find the answer?

Our community is visited by hundreds of web development professionals every day. Ask your question and get a quick answer for free.

Ask a Question

Write quick answer

Do you know the answer to this question? Write a quick response to it. With your help, we will make our community stronger.

Similar questions

Find the answer in similar questions on our website.