0

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'
            ]
        ]
    ]
]
1
  • How do you want it to be sorted? Commented Mar 15, 2009 at 19:42

2 Answers 2

3

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);
}
Sign up to request clarification or add additional context in comments.

1 Comment

Well, you'll have a problem with directories or files because you must use different algorithms for the two of them (ksort for directories level, sort for files). IMO, the best options if to make files arrays more like "filename" => true rather than 0 => "filename" and apply the mulsort I just put.
0

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);

Comments