【问题标题】:PHP - sort hash array by key lengthPHP - 按键长度对哈希数组进行排序
【发布时间】:2011-04-26 17:07:21
【问题描述】:

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

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

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

我希望它们按这个顺序排列

  1. 真的很长的名字
  2. 媒体名称
  3. 短名称

中间名短名

非常感谢

【问题讨论】:

    标签: php arrays sorting key


    【解决方案1】:

    要绝对使用 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
    )
    

    我已经测试了这段代码。

    【讨论】:

      【解决方案2】:

      在 PHP7+ 中,您可以将uksort() 与太空船运算符和匿名函数一起使用,如下所示:

      uksort($array, function($a, $b) {
          return strlen($b) <=> strlen($a);
      });
      

      【讨论】:

        【解决方案3】:

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

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

        【讨论】:

          【解决方案4】:

          根据长度对键进行排序的一个限制是:相等长度的键不会重新排序。假设我们需要在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/>";
          }
          

          输出将是:

          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 例如(或其他)在两种排序方法中的顺序。第二种方法看起来更好。可能有更简单的方法来解决这个问题,但希望这对某人有所帮助......

          【讨论】:

            【解决方案5】:

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

            • 2.01 秒 ... uksort 与匿名 create_function(通过 cojam)
            • 0.28 秒 ... array_multisort(由 Gumbo 提供)
            • 2.69 秒 ... 具有非匿名函数的 uksort(由 Colin Herbert 撰写) - 让我感到惊讶,
            • 0.15 秒 ... 简单的 foreach + arsort

            有时简单的 foreach 仍然会获胜。 显然,使用动态 PHP 功能会降低性能。

            【讨论】:

              【解决方案6】:

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

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

              【讨论】:

                【解决方案7】:

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

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

                【讨论】:

                  【解决方案8】:

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

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

                  这里$keys$arr 的键长度的数组。该数组按降序排序,然后使用array_multisort$arr 的值进行排序。

                  【讨论】:

                  • 出于好奇,这是否比uksort() 有性能优势?
                  • @thetaiko:不,我不这么认为。但是您必须进行概要分析才能确定。主要区别在于不需要自定义比较函数,因为通过比较键值来区分顺序。
                  • 我喜欢这个,因为它很容易变成一行
                  【解决方案9】:

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

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

                  资源:

                  【讨论】:

                    【解决方案10】:

                    您可以使用用户定义的键排序函数作为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”。

                    【讨论】:

                      【解决方案11】:

                      看看uksort

                      【讨论】:

                        猜你喜欢
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 2020-10-14
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 2020-04-05
                        相关资源
                        最近更新 更多