PHP - 按密钥长度排序哈希数组

时间:2010-10-17 22:19:38

标签: php arrays sorting key

我找到了一些按值排序的答案,但不是关键。

我想做的是反向排序,所以:

    $nametocode['reallylongname']='12';
    $nametocode['shortname']='10';
    $nametocode['mediumname']='11';

我希望他们按此顺序

  1. reallylongname
  2. mediumname
  3. 短名称
  4. 中名短名

    非常感谢

10 个答案:

答案 0 :(得分:23)

使用array_multisort的另一种解决方案:

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

此处$keys$arr键的长度数组。该数组按降序排序,然后用于使用$arrarray_multisort的值进行排序。

答案 1 :(得分:8)

您可以使用用户定义的键排序功能作为uksort的回调:

function cmp($a, $b)
{
    if (strlen($a) == strlen($b))
        return 0;
    if (strlen($a) > strlen($b))
        return 1;
    return -1;
}

uksort($nametocode, "cmp");

foreach ($nametocode as $key => $value) {
    echo "$key: $value\n";
}

快速注意 - 要反转排序,只需切换“1”和“-1”。

答案 2 :(得分:8)

基于@thetaiko的答案,更简单的回调:

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

uksort($nametocode, "sortByLengthReverse");

资源:

答案 3 :(得分:4)

看看我强大的内联方法。为后代保留全球空间!

uksort($data, create_function('$a,$b', 'return strlen($a) < strlen($b);'));

答案 4 :(得分:2)

我对一些排序算法进行了基准测试,因为性能对我的项目很重要 - 这是我发现的(平均结果运行1000x,排序字段有cca 300元素,密钥大小为3-50个字符):

  • 2.01秒... uksort with anonymous create_function(by cojam)
  • 0.28秒... array_multisort(由Gumbo提供)
  • 2.69秒...具有非匿名功能的uksort(由Colin Herbert提供) - 让我感到惊讶,
  • 0.15秒......简单的foreach + arsort

有时简单的foreach仍然获胜。 显然,使用动态PHP功能会有一些性能损失。

答案 5 :(得分:2)

基于长度对键进行排序时的一个限制是:不重新排序等长键。假设我们需要按descending顺序按长度订购密钥。

$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/>";
}

输出将是:

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
)

请注意两个排序方法中elephantdog的顺序(例如(或其他))。第二种方法看起来更好。可能有更简单的方法来解决这个问题,但希望这有助于某些人......

答案 6 :(得分:1)

查看uksort

答案 7 :(得分:0)

下面的代码按密钥的字符串长度对PHP哈希数组进行排序,然后使用区分大小写的密钥本身,使用lambda函数按升序排序:

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

此代码的反向顺序相同:

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

答案 8 :(得分:0)

要绝对使用 uksort ,您可以这样做:

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

输出:

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

我已经测试了这段代码。

答案 9 :(得分:-1)

一个简单的问题需要一个简单的解决方案; - )

arsort($nametocode, SORT_NUMERIC);
$result = array_keys($nametocode);