Search code examples
phparraysmultidimensional-arraydynamic-arrays

How to generate array path for specific key by looping through dynamic multidimensional array?


I have a dynamic multidimensional array as below:

$cityList = [
  'AUS' => [
    'VIC' => [
      'population' => [ 'total' => '5M']
      'Richmond' => [
        'population' => [ 'total' => '0.15M']
      ]
    ],
    'NSW' => [
      'Carlton' => [
         'population' => [ 'total' => '8M']
      ]
    ]
  ]
];

Here, the column population may or may not be present on all dimension. However, if it's present then it'll always have total as sub array as above.

Now, I need to traverse through the array and generate all path to population if exist.

I've written code as below:

public function fetchAllPopulation(array $cityList, $path = '', &$cityWithPopulation)
    {
        foreach ($cityList as $key => $city) {
            if (is_array($city) && $key != 'population') {
                $path .= $path == '' ? $key: "##$key";
                $this->fetchAllPopulation($city, $path, $cityWithPopulation);
            } else {
                $population = $city['total'];
                $cityWithPopulation[$path] = $population;
            }
        }
        return $assetWithPathsAndIds;
    }

Expected output:

[
 'AUS##VIC' => '5M',
 'AUS##VIC##Richmond' => '0.15M',
 'AUS##NSW##Carlton' => '8M'
]

Actual output:

[
 'AUS##VIC' => '5M',
 'AUS##VIC##Richmond' => '0.15M',
 'AUS##VIC##NSW##Carlton' => '8M' // this is incorrect
]

The problem is if any column has more than 2 dimensions, then the previous key will be appended on the next one as above.

Any feedback or correction to my code will be appreciated. Thanks!


Solution

  • This way:

    public function fetchAllPopulation(array $cityList, $path, &$cityWithPopulation)
        {
            foreach ($cityList as $key => $city) {
                if (is_array($city) && $key != 'population') {
                    $subPath = $path . ($path == '' ? $key: "##$key");
                    $this->fetchAllPopulation($city, $subPath, $cityWithPopulation);
                } else {
                    $population = $city['total'];
                    $cityWithPopulation[$path] = $population;
                }
            }
            return $assetWithPathsAndIds;
        }