warden
warden

Reputation:

Recursively sort a multidimensional array representing a file system with directories as keys and filenames as indexed subarrays

I need to sort a multidimensional array which represents filesystem structure. How can I sort the directories by their keys and the filenames by their values?

[
    'dir1' => [
        'dir2' => [
            'dir3' => [
                'dir4' => [
                    'file1.php',
                    'abc.php'
                ]
            ],
            'file2.php',
            'abc.php'
        ]
    ],
    'abc' => [
        'abc' => [
            'abc' => [
                'file5.php'
            ]
        ]
    ]
]

Upvotes: 0

Views: 3155

Answers (2)

mickmackusa
mickmackusa

Reputation: 48101

To sort the variable depth structure use recursion to traverse all levels. Identify directories, not by their key, but by their value datatype -- if an array, then it is a directory which needs to be naturally sorted by key. If dealing with a leafnode, then the indexes do not need to be preserved and the values should be sorted naturally.

By separating the two item types, sorting correctly is simple. After soring each "bucket", merge them together to overwrite $array. Note that if you have a directory named 0, then this numeric key will bump up the starting point of any index-keyed files in the same directory.

This will present your directories and files in a logical, yet human-friendly way.

Code: (Demo)

function sortFileSystem(array &$array)
{
    $dirs = [];
    $files = [];
    foreach ($array as $k => &$v) {
        if (is_array($v)) {
            (__FUNCTION__)($v);  // recurse
            $dirs[$k] = $v;  // preserve key
        } else {
            $files[] = $v;  // key is unneeded
        }
    }
    ksort($dirs, SORT_NATURAL);
    sort($files, SORT_NATURAL);
    $array = array_merge($dirs, $files); // put dirs before files
}

sortFileSystem($array);
var_export($array);

Upvotes: 0

Julian Aubourg
Julian Aubourg

Reputation: 11436

http://php.net/sort#51088

replace sort($a) at the beginning of the mulsort function by ksort($a)

EDIT: sorry, just change the mulsort code to :

function mulsort(&$a)
{
 ksort($a);
 foreach($a as &$value)
    if (is_array($value))
        mulsort($value);
}

Upvotes: 3

Related Questions