Home > Blockchain >  Group a 2d array based on multiple column values
Group a 2d array based on multiple column values

Time:11-13

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”
           ],
       ]
     ]

]

CodePudding user response:

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
                        )

                )

        )

)

CodePudding user response:

  • Loop over each row
  • Create convenient variables from the row's associative elements with extract()
  • Push the row into the nested associative structure using two of the three generated variables

Code: (Demo)

$result = [];
foreach ($students as $student) {
    extract($student);
    $result[$country][$school] = $student;
}
var_export($result);

It is not at all necessary to instantiate/declare parent elements before pushing child elements when using square brace pushing syntax. If you are using array_push(), the parent element must be declared in advance.

There are more abstract and less attractive ways to code this task using array_reduce() or array destructuring:

Related:

  • Related