PHP - sort hash array by key length

后端 未结 11 1217
星月不相逢
星月不相逢 2021-01-04 08:40

I\'ve found a few answers to sorting by value, but not key.

What I\'d like to do is a reverse sort, so with:

    $nametocode[\'reallylongname\']=\'12         


        
相关标签:
11条回答
  • 2021-01-04 08:58

    The code below sorts the PHP hash array by string length of the key, then by the case-sensitive key itself, both in ascending order, using a lambda function:

    uksort($yourArray, function ($a, $b) { 
       return (strlen($a) == strlen($b) ? strcmp($a, $b) : strlen($a) - strlen($b));
    });
    

    This code does the same in reverse order:

    uksort($yourArray, function ($b, $a) { 
       return (strlen($a) == strlen($b) ? strcmp($a, $b) : strlen($a) - strlen($b));
    });
    
    0 讨论(0)
  • Take a look on uksort.

    0 讨论(0)
  • 2021-01-04 09:03

    Based on @thetaiko answer, with a simpler callback :

    function sortByLengthReverse($a, $b){
        return strlen($b) - strlen($a);
    }
    
    uksort($nametocode, "sortByLengthReverse");
    

    Resources :

    • php.net - uksort()
    • php.net - Sorting arrays
    • php.net - strlen()
    0 讨论(0)
  • 2021-01-04 09:05

    One limitation while sorting the keys on the basis of length is that: equal length keys are not re-ordered. Say we need to order the keys by length in descending order.

    $arr = array(
        "foo 0" => "apple",
        "foo 1" => "ball",
        "foo 2 foo 0 foo 0" => "cat",
        "foo 2 foo 0 foo 1 foo 0" => "dog",
        "foo 2 foo 0 foo 1 foo 1" => "elephant",
        "foo 2 foo 1 foo 0" => "fish",
        "foo 2 foo 1 foo 1" => "giraffe"
    );
    
    debug($arr, "before sort");
    $arrBad = $arr;
    sortKeysDescBAD($arrBad);
    debug($arrBad, "after BAD sort");
    sortKeysDescGOOD($arr);
    debug($arr, "after GOOD sort 2");
    
    function sortKeysDescBAD(&$arrNew) {
        $arrKeysLength = array_map('strlen', array_keys($arrNew));
        array_multisort($arrKeysLength, SORT_DESC, $arrNew);
        //return max($arrKeysLength);
    }
    
    function sortKeysDescGOOD(&$arrNew) {
        uksort($arrNew, function($a, $b) {
            $lenA = strlen($a); $lenB = strlen($b);
            if($lenA == $lenB) {
                // If equal length, sort again by descending
                $arrOrig = array($a, $b);
                $arrSort = $arrOrig;
                rsort($arrSort);
                if($arrOrig[0] !== $arrSort[0]) return 1;
            } else {
                // If not equal length, simple
                return $lenB - $lenA;
            }
        });
    }
    
    function debug($arr, $title = "") {
        if($title !== "") echo "<br/><strong>{$title}</strong><br/>";
        echo "<pre>"; print_r($arr); echo "</pre><hr/>";
    }
    

    Output will be:

    before sort
    Array
    (
        [foo 0] => apple
        [foo 1] => ball
        [foo 2 foo 0 foo 0] => cat
        [foo 2 foo 0 foo 1 foo 0] => dog
        [foo 2 foo 0 foo 1 foo 1] => elephant
        [foo 2 foo 1 foo 0] => fish
        [foo 2 foo 1 foo 1] => giraffe
    )
    
    after BAD sort
    Array
    (
        [foo 2 foo 0 foo 1 foo 0] => dog
        [foo 2 foo 0 foo 1 foo 1] => elephant
        [foo 2 foo 0 foo 0] => cat
        [foo 2 foo 1 foo 0] => fish
        [foo 2 foo 1 foo 1] => giraffe
        [foo 0] => apple
        [foo 1] => ball
    )
    
    after GOOD sort
    Array
    (
        [foo 2 foo 0 foo 1 foo 1] => elephant
        [foo 2 foo 0 foo 1 foo 0] => dog
        [foo 2 foo 1 foo 1] => giraffe
        [foo 2 foo 1 foo 0] => fish
        [foo 2 foo 0 foo 0] => cat
        [foo 1] => ball
        [foo 0] => apple
    )
    

    Notice the order of elephant and dog for example (or others) in two sorting methods. The second method looks better. There may be easier ways to solve this but hope this helps someone...

    0 讨论(0)
  • 2021-01-04 09:06

    To absolutely use uksort you can do like this:

    $nametocode['reallylongname']='12';
    $nametocode['name']='17';
    $nametocode['shortname']='10';
    $nametocode['mediumname']='11';
    
    uksort($nametocode, function($a, $b) {
       return strlen($a) - strlen($b);
    });
    
    array_reverse($nametocode, true);
    

    Output:

    Array
    (
       [reallylongname] => 12
       [mediumname] => 11
       [shortname] => 10
       [name] => 17
    )
    

    I have tested this code.

    0 讨论(0)
  • 2021-01-04 09:08

    Another solution using array_multisort:

    $keys = array_map('strlen', array_keys($arr));
    array_multisort($keys, SORT_DESC, $arr);
    

    Here $keys is an array of the lengths of the keys of $arr. That array is sorted in descending order and then used to sort the values of $arr using array_multisort.

    0 讨论(0)
提交回复
热议问题