Search code examples
phparraysmultidimensional-arraygroupingassociative-array

Group a 2d array based on multiple column values


I have a two dimensional array of students from different schools and countries. I want them to be grouped by name of school and country.

How can I create the nested key structure?

Example:

$students = [
  [
    "country" => "japan",
    "school"  => "kyoto university",
    "name"    => "Naruto Uzumaki"
  ],
  [
    "country" => "usa",
    "school"  => "harvard university",
    "name"    => "Naruto Uzumaki"
  ], 
  [
    "country" => "japan",
    "school"  => "tokyo university",
    "name"    => "sasuke Uchiha"
  ],
  [
    "country" => "japan",
    "school"  => "tokyo university",
    "name"    => "kakashi hatake"
  ],
];

Desired result:

[
  “japan” => [
      “kyoto university” => [
          [
            “country” => “japan”,
            “school”  => “kyoto university”,
            “name”    => “Naruto Uzumaki”
          ],
      ],

      “tokyo university” => [
          [
            “country” => “japan”,
            “school”  => “tokyo university”,
            “name”    => “sasuke Uchiha”
          ],
          [
            “country” => “japan”,
            “school”  => “tokyo university”,
            “name”    => “kakashi hatake”
          ],
      ],

   ],
   

   “usa” => [
       “harvard university” => [
           [
             “country” => “usa”,
             “school”  => “harvard university”,
             “name”    => “Naruto Uzumaki”
           ],
       ]
     ]

]


Solution

  • Pretty much creating an object or using an existing one. First create country object if not exists, then create school object under it (if not exists) then push to it.

    $result = [];
    foreach ($students as $student) {
        $country = $student['country'];
        $school = $student['school'];
        $result[$country] = isset($result[$country]) ? $result[$country] : [];
        $result[$country][$school] = isset($result[$country][$school]) ? $result[$country][$school] : [];
        $result[$country][$school][] = $student;
    }
    print_r($result);
    

    Output:

    Array
    (
        [japan] => Array
            (
                [kyoto university] => Array
                    (
                        [0] => Array
                            (
                                [country] => japan
                                [school] => kyoto university
                                [name] => Naruto Uzumaki
                            )
    
                    )
    
                [tokyo university] => Array
                    (
                        [0] => Array
                            (
                                [country] => japan
                                [school] => tokyo university
                                [name] => sasuke Uchiha
                            )
    
                        [1] => Array
                            (
                                [country] => japan
                                [school] => tokyo university
                                [name] => kakashi hatake
                            )
    
                    )
    
            )
    
        [usa] => Array
            (
                [harvard university] => Array
                    (
                        [0] => Array
                            (
                                [country] => usa
                                [school] => harvard university
                                [name] => Naruto Uzumaki
                            )
    
                    )
    
            )
    
    )