PHP - sort hash array by key length

2020-07-03 03:51发布

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';
    $nametocode['shortname']='10';
    $nametocode['mediumname']='11';

I'd like them to be in this order

  1. reallylongname
  2. mediumname
  3. shortname

mediumname shortname

Many thanks

11条回答
女痞
2楼-- · 2020-07-03 04:35

I have benchmarked some of sorting algorithms since performance is important for my project - here's what I've found (averaged result ran 1000x, sorted field had cca 300 elements with key size 3-50 chars):

  • 2.01 sec ... uksort with anonymous create_function (by cojam)
  • 0.28 sec ... array_multisort (by Gumbo)
  • 2.69 sec ... uksort with non-anonymous function (by Colin Herbert) - surprise for me,
  • 0.15 sec ... simple foreach + arsort

Sometime simple foreach still wins. Using dynamic PHP features has some performance penalty, obviously.

查看更多
做自己的国王
3楼-- · 2020-07-03 04:37

Take a look on uksort.

查看更多
再贱就再见
4楼-- · 2020-07-03 04:38

Based on @thetaiko answer, with a simpler callback :

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

uksort($nametocode, "sortByLengthReverse");

Resources :

查看更多
一夜七次
5楼-- · 2020-07-03 04:38

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...

查看更多
beautiful°
6楼-- · 2020-07-03 04:39

Behold my powerful inline methodologies. Preserve global space for the generations to come!

uksort($data, create_function('$a,$b', 'return strlen($a) < strlen($b);'));
查看更多
登录 后发表回答