Home > Software engineering >  Sort associative array by key like filenames on a computer
Sort associative array by key like filenames on a computer

Time:03-18

I have following structure:

$arr = [
    'children' => [
        'align.php' => [],
        'default.php' => [],
        'test.php' => [],
        'default-2.php' => [],
    ]
]

Currently I am using

ksort($arr['children'])

and it sorts it like that:

$arr = [
    'children' => [
        'align.php' => [],
        'default-2.php' => [],
        'default.php' => [],
        'test.php' => [],
    ]
]

However, I need the array to be in this order:

$arr = [
    'children' => [
        'align.php' => [],
        'default.php' => [],
        'default-2.php' => [],
        'test.php' => [],
    ]
]

I've tried the NATURAL_SORT flag, but that didn't work. What other options are there?

CodePudding user response:

You can extract the file names using the pathinfo function, and then compare them in the callback function in the uksort function.

uksort($arr['children'], function($a, $b){
    $a = pathinfo($a);
    $b = pathinfo($b);
    return $a['filename'] == $b['filename'] ? 
        $a['basename'] <=> $b['basename'] :
        $a['filename'] <=> $b['filename'];

});

fiddle

A more complex sorting of file names with multiple dots is solved, for example, like this

/* Example:
    a
    a.class
    a.class.php
    a.class.php-1
    a.class-1.php
    a.class-1.php-1
    a-1
    a-1.class.php
    a-1.class-1
    a-1.class-1.php-1
*/

uksort($arr['children'], function($a, $b){
    $a = explode('.', $a);
    $b = explode('.', $b);
    $s = '';
    $i = 0;
    while (isset($a[$i]) && isset($b[$i]) && $a[$i] == $b[$i]) {
        $s .= $a[$i  ] . '.'; 
    }
    return $s . ($a[$i] ?? '') <=> $s . ($b[$i] ?? '');
});

fiddle

  • Related