简体   繁体   中英

PHP Recursive Loop using UASORT on Multidimensional Array

I am writing a script that loops through a multidimensional array and it's working as hoped (sort of) but I get errors that I just can't remedy.

I am still not that comfortable building loops to manage nested arrays.

Here is my code. The goal is to sort each layer by the value of the sequence key and in the end I export the array as json.

The sequence key may or may not exist in every sub array so that may need some sort of if clause

<?php
$list = [
        "key" => "book",
        "sequence" => 1,
        "items" => [
            [
                "key" => "verse",
                "sequence" => 2,
                "items" => [
                    ["sequence" => 3],
                    ["sequence" => 1],
                    ["sequence" => 2],
                ],
            ],
            [
                "key" => "page",
                "sequence" => 1,
                "items" => [
                    [
                        "key" => "page",
                        "sequence" => 2,
                        "items" => [
                            ["sequence" => 2],
                            ["sequence" => 1],
                            ["sequence" => 3],
                        ],
                    ],
                    [
                        "key" => "paragraph",
                        "sequence" => 1,
                        "items" => [
                            ["sequence" => 2],
                            ["sequence" => 1],
                            ["sequence" => 3],
                        ],
                    ],
                ],
            ],
        ],
    ];

function sortit(&$array){

    foreach($array as $key => &$value){
        //If $value is an array.
        if(is_array($value)){

            if($key == "items"){
                uasort($value, function($a,&$b) {
                   return $a["sequence"] <=> $b["sequence"];
                });

            }
            //We need to loop through it.
            sortit($value);
        } else{
            //It is not an array, so print it out.
            echo $key . " : " . $value . "<br/>";
        }
    }
}


sortit($list);

echo "<pre>";

print_r($list);

?>

Here is the output and error I am getting, and I think I understand why the error is being thrown but at the same time I can not implement the proper checks needed to fix the error.

key : book
sequence : 1
key : page
sequence : 1

E_WARNING : type 2 -- Illegal string offset 'sequence' -- at line 39

E_NOTICE : type 8 -- Undefined index: sequence -- at line 39
sequence : 1
sequence : 2
sequence : 3
sequence : 1
key : page

E_WARNING : type 2 -- Illegal string offset 'sequence' -- at line 39

E_NOTICE : type 8 -- Undefined index: sequence -- at line 39
sequence : 1
sequence : 2
sequence : 3
sequence : 2
key : verse

Not that I am worried to much but another thing that I would like is the array to still be structured in the original order, ie: key, sequence, items

Using usort and array references makes it straightforward. If we're dealing with an array with a set item key, sort the item array and recurse on its children, otherwise, we're at a leaf node and can return.

function seqSort(&$arr) {
    if (is_array($arr) && array_key_exists("items", $arr)) {
        usort($arr["items"], function ($a, $b) {
            return $a["sequence"] - $b["sequence"];
        });

        foreach ($arr["items"] as &$item) {
            $item = seqSort($item);
        }
    }

    return $arr;
}

Result:

array (
  'key' => 'book',
  'sequence' => 1,
  'items' => 
  array (
    0 => 
    array (
      'key' => 'page',
      'sequence' => 1,
      'items' => 
      array (
        0 => 
        array (
          'key' => 'page',
          'sequence' => 1,
          'items' => 
          array (
            0 => 
            array (
              'sequence' => 1,
            ),
            1 => 
            array (
              'sequence' => 2,
            ),
            2 => 
            array (
              'sequence' => 3,
            ),
          ),
        ),
      ),
    ),
    1 => 
    array (
      'key' => 'verse',
      'sequence' => 2,
      'items' => 
      array (
        0 => 
        array (
          'sequence' => 1,
        ),
        1 => 
        array (
          'sequence' => 2,
        ),
        2 => 
        array (
          'sequence' => 3,
        ),
      ),
    ),
  ),
)

Try it!

Note that the outermost structure is a root node that isn't part of an array and can't be sorted (this may be unintentional and causing confusion).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM