【问题标题】:PHP sort array by two field values [duplicate]PHP按两个字段值排序数组[重复]
【发布时间】:2011-06-02 17:31:58
【问题描述】:

我有一个这样的数组

大批 ( [0] => 数组(“目的地”=>“悉尼”, "航空公司" => "airline_1", "one_way_fare" => 100, “return_fare => 300 ), [2] => 数组(“目的地”=>“悉尼”, "航空公司" => "airline_2", "one_way_fare" => 150, “return_fare => 350 ), [3] => Array("目的地" => "悉尼", "航空公司" => "airline_3", "one_way_fare" => 180, “return_fare => 380 ) )

如何按 return_fare asc 、 one_way_fare asc 对值进行排序?

我尝试了array_multisort(),但我最终得到了混淆数据..

asort 只适用于一维数组,我需要按两个或多个值排序,我怎样才能像在 SQL 中那样,按 field1 asc,field2 asc 排序?

【问题讨论】:

    标签: php arrays sorting


    【解决方案1】:

    array_multisort() 是正确的函数,你一定是搞砸了:

    // Obtain a list of columns
    foreach ($data as $key => $row) {
        $return_fare[$key]  = $row['return_fare'];
        $one_way_fare[$key] = $row['one_way_fare'];
    }
    
    // Sort the data with volume descending, edition ascending
    array_multisort($return_fare, SORT_ASC, $one_way_fare, SORT_ASC, $data);
    

    如果您查看 array_multisort() 的 PHP 手册页上的 cmets,您会发现一个非常有用的 array_orderby() 函数,它允许您将上述内容缩短为:

    $sorted = array_orderby($data, 'return_fare', SORT_ASC, 'one_way_fare', SORT_ASC);
    

    为避免循环使用array_column()(自 PHP 5.5.0 起):

    array_multisort(array_column($data, 'return_fare'),  SORT_ASC,
                    array_column($data, 'one_way_fare'), SORT_ASC,
                    $data);
    

    【讨论】:

    • 谢谢..!我想我完全按照你的建议做了。尽管在手册页 cmets 上找不到 array_orderby() 函数
    • 非常感谢。 array_orderby 为我工作。但是我必须复制 PHP 网站的功能.. :)
    【解决方案2】:

    除了array_multisort(),它要求你先构建列数组,还有usort(),它不需要这样的东西。

    usort($data, function($a, $b) { 
        $rdiff = $a['return_fare'] - $b['return_fare'];
        if ($rdiff) return $rdiff; 
        return $a['one_way_fare'] - $b['one_way_fare']; 
    }); // anonymous function requires PHP 5.3 - use "normal" function earlier
    

    【讨论】:

    • 或更简单地说,return $a['return_fare'] - $b['return_fare'] ?: a['one_way_fare'] - $b['one_way_fare']; 一切都比array_multisort() 感觉更自然
    • 我偶然发现了这个,我认为应该说array_multisort 似乎比usort 快得多 - 你可以在这里找到一个例子sandbox.onlinephpfunctions.com/code/…
    • 现在很可能是这种情况(早在 2011 年还没有 arrarray_column,因此您必须自己构建数组,这大大减慢了速度)。
    • 生成两个数组的foreach 循环很可能优于两个单独的array_column() 调用...如果您担心微优化。两次array_column() 调用的好处是代码简洁和避免进行两个变量声明。
    【解决方案3】:

    另一个使用 spaceship 运算符的示例。

    usort($data, function($a, $b) { 
        return $a['return_fare'] <=> $b['return_fare'] ?: $a['one_way_fare'] <=> $b['one_way_fare'];
    });
    

    【讨论】:

    • 这可以通过单个宇宙飞船算子比较来完成。
    • 但你不告诉我们@mickmackusa 是怎么回事?
    • 我在重复页面上的回答演示了如何执行此操作。 @codemonkey
    • 如果你喜欢,这里还有一些:stackoverflow.com/… 作为记录,如果你在比较中进行函数调用,那么我建议使用多个宇宙飞船,但如果没有函数调用,那么它最好使用一艘宇宙飞船。我的旧答案可能不符合这条线。
    • 啊哈。我考虑过串联,但知道这不安全——我没有想到数组,谢谢。
    【解决方案4】:

    或者你可以使用uasort如下

    uasort($arr, function($a,$b){
        $c = $a['return_fare'] - $b['return_fare'];
        $c .= $a['one_way_fare'] - $b['one_way_fare'];
        return $c;
    });
    

    Fiddle

    【讨论】:

    • 这在使用十进制值排序时不起作用
    • 这是一个很棒的提示:我试图进行双重排序(分组作业 ID,然后在组内订购产品 ID),这完美地完成了这个技巧(我正在寻找一个 MySQL 多列排序解决方案,我尝试过 array_multisort 并且它破坏了组中的其他有序部分 - 这是唯一让我能够以我可以阅读和理解的方式获得所需顺序的解决方案,这在重构时非常重要更进一步)
    • 我永远不会使用由两个差值组成的串联字符串。即使在可行的情况下,也有更清洁的技术可用。
    【解决方案5】:

    我会以一种可以概括的方式回答这个问题,不管你想对多少项目进行排序!

    return_fare 排序,然后按one_way_fare

    usort($data, function($a, $b) {
       if ($a['return_fare'] != $b['return_fare']) {
          return $a['return_fare'] <=> $b['return_fare'];
       }
    
       return $a['one_way_fare'] <=> $b['one_way_fare'];
    });
    

    return_fare排序,然后是one_way_fare,然后是destination

    usort($data, function($a, $b) {
       if ($a['return_fare'] != $b['return_fare']) {
          return $a['return_fare'] <=> $b['return_fare'];
       }
    
       if ($a['one_way_fare'] != $b['one_way_fare']) {
          return $a['one_way_fare'] <=> $b['one_way_fare'];
       }
    
       return strnatcasecmp($a['destination'], $b['destination']);
    });
    

    仅按return_fare排序:

    usort($data, function($a, $b) {
       return $a['return_fare'] <=> $b['return_fare'];
    });
    

    注意:您不必对usort 使用匿名函数!

    function cmp($a, $b) {
       return $a['return_fare'] <=> $b['return_fare'];
    }
    
    usort($data, 'cmp');
    
    
    // Use a function inside a class:
    class MyClass {
       public static function compare($a, $b) {
          return $a['return_fare'] <=> $b['return_fare'];
       }
    }
    
    usort($data, ['MyClass', 'compare']);
    

    您也可以使用 Elvis Operator (?:) 链接这些:

    usort($data, function($a, $b) {
          return $a['return_fare'] <=> $b['return_fare'] ?:
                 $a['one_way_fare'] <=> $b['one_way_fare'] ?:
                 strnatcasecmp($a['destination'], $b['destination']);
    });
    

    最后一个示例使用了 Spaceship Operator (&lt;=&gt;) 和 Elvis Operator (?:)。编程不是很好吗?

    【讨论】:

      【解决方案6】:

      哦,我又设法解决了我自己的问题......

      function array_multi_sort($array, $on1,$on2, $order=SORT_ASC) 
      {
      
          foreach($array as $key=>$value){
              $one_way_fares[$key] = $value[$on2];
              $return_fares[$key] = $value[$on1];
          }
      
          array_multisort($return_fares,$order,$one_way_fares,$order,$array);
      }
      

      问题是我错过了array_multisort($return_fares,$order,$one_way_fares,$order,$array); 上的最后一个参数 $array

      早点!

      【讨论】:

        猜你喜欢
        • 2017-08-01
        • 2012-04-17
        • 2011-06-01
        • 1970-01-01
        • 1970-01-01
        • 2014-12-02
        • 2013-03-11
        • 1970-01-01
        相关资源
        最近更新 更多