Convert array with 3-element rows into hierarchical array with 3 levels
Asked Answered
S

4

5

I have an array that looks like this:

[98] => Array
(
    [City] => Caracas
    [Country] => Venezuela
    [Continent] => Latin America
)

[99] => Array
(
    [City] => Cairo
    [Country] => Egypt
    [Continent] => Middle East
)

[105] => Array
(
    [City] => Abu Dhabi
    [Country] => United Arab Emirates
    [Continent] => Middle East
)

[106] => Array
(
    [City] => Dubai
    [Country] => United Arab Emirates
    [Continent] => Middle East
)

[107] => Array
(
    [City] => Montreal
    [Country] => Canada
    [Continent] => North America
)

I am trying to group this array into a new multi-dimensional array structure, so that it outputs something like:

Continent
    - Country Name    
      -- Cities under Every Country

Exact desired result:

array (
  'Latin America' => 
  array (
    'Venezuela' => 
    array (
      0 => 'Caracas',
    ),
  ),
  'Middle East' => 
  array (
    'Egypt' => 
    array (
      0 => 'Cairo',
    ),
    'United Arab Emirates' => 
    array (
      0 => 'Abu Dhabi',
      1 => 'Dubai',
    ),
  ),
  'North America' => 
  array (
    'Canada' => 
    array (
      0 => 'Montreal',
    ),
  ),
)
Scute answered 11/11, 2013 at 17:1 Comment(3)
Out of curiosity, how is the array being generated?Discotheque
I have a SQL query that returns the array.Scute
Maybe it's much easier to organize data by SQL grouping.Gavelkind
R
10
$array = array(
    98 => array(
        'City' => 'Caracas',
        'Country' => 'Venezuela',
        'Continent' => 'Latin America',
    ),
    99 => array(
        'City' => 'Cairo',
        'Country' => 'Egypt',
        'Continent' => 'Middle East',
    ),
    105 => array(
        'City' => 'Abu Dhabi',
        'Country' => 'United Arab Emirates',
        'Continent' => 'Middle East',
    ),
    106 => array(
        'City' => 'Dubai',
        'Country' => 'United Arab Emirates',
        'Continent' => 'Middle East',
    ),
    107 => array(
        'City' => 'Montreal',
        'Country' => 'Canada',
        'Continent' => 'North America',
    )
);

$newArray = array();
foreach ($array as $row)
{
   $newArray[$row['Continent']][$row['Country']][] = $row['City'];
}

print_r($newArray);
Rodmur answered 11/11, 2013 at 17:8 Comment(0)
D
1

A couple more alternative approaches:

Use "array destructuring" in a body-less foreach() to populate the hierarchical structure (Demo) (Further about the technique)

$result = [];
foreach (
    $array as
    [
        'Continent' => $a,
        'Country' => $b,
        'City' => $result[$a][$b][]
    ]
);
var_export($result);

Use array_reduce() to avoid declaring a result variable in the global scope. (Demo)

var_export(
    array_reduce(
        $array,
        function($result, $row) {
            $result[$row['Continent']][$row['Country']][] = $row['City'];
            return $result;
        }
    )
);
Dragonroot answered 15/1, 2023 at 6:49 Comment(0)
S
0

What about this solution:

function arrayToMultiDimensionalArray(array $elements, array $dimensions)
{
    $output = [];

    foreach ($elements as $element) {
        $outputElement =& $output;

        // Foreach to build up the dimensions
        foreach ($dimensions as $dimension) {
            $outputElement =& $outputElement[$element[$dimension]];
        }

        $outputElement[] = $element['City'];
    }

    return $output;
}

$dimensions = ['Continent', 'Country'];

$tree = arrayToMultiDimensionalArray($array, $dimensions);
Sarre answered 12/11, 2021 at 19:55 Comment(3)
@Dragonroot Just change $outputElement[] = $element; to $outputElement[] = $element['City']; problem solvedSarre
@Dragonroot A "thank you" would be nice.Sarre
Stack Overflow doesn't do "thank you"s. Just the same, you can thank me for bringing to your attention that your answer wasn't (and still isn't) the best version of itself. I know what your script is doing, but there will be many PHP developers who won't and they might not use it because they don't understand how it works.Dragonroot
T
-1

I think you just need to loop in your array and create a new one using some values as keys and some other as value, for example

$new_array = array();
foreach($array as $val)
{ 
     $new_array[$val['Continent']][$val['Country']] = array('City' => $val['City']);
}  

Live Sample

Tenuous answered 11/11, 2013 at 17:11 Comment(1)
This answer is incorrect because it only allows one city per subset. Proof: 3v4l.org/aDqFQDragonroot

© 2022 - 2024 — McMap. All rights reserved.