【问题标题】:Sort multidimensional array by date column, then use other column values if dates are the same按日期列对多维数组进行排序,如果日期相同,则使用其他列值
【发布时间】:2011-07-09 01:40:15
【问题描述】:

我有一个存储人的多维数组。

Array (
   id93294 => array (
       Name => "Tom Anderson",
       Birthday => "03/17/1975",
       Hometown => 'St. Louis',
       CurrentLocation => 'Mars'
   ),
   id29349 => (array (
       Name => "Tom Anderson",
       Birthday => "03/17/1975",
       Hometown => 'New York',
       CurrentLocation => 'New York'
   )
)

有点像,除了为人们提供更多信息,所以我想首先按生日排序,然后按另一个属性排序(如果他们的家乡与他们当前的位置匹配)但是一旦我对数组进行第二次排序,它就会丢失我用生日做的第一类...

如何在不打乱我之前的排序的情况下多次排序。

附:我正在使用 uasort。

【问题讨论】:

  • 不要连续排序;正确定义排序函子以考虑树的所有层。

标签: php arrays multidimensional-array sorting


【解决方案1】:

多年后,PHP7+ 提供了一种更简洁、更简洁的技术……宇宙飞船运算符和“标准”的平衡数组。

代码:(Demo)

uasort($array, function($a, $b) {
    return [strtotime($a['Birthday']), $a['Hometown'] !== $a['CurrentLocation'], $a['Name']]
           <=>
           [strtotime($b['Birthday']), $b['Hometown'] !== $b['CurrentLocation'], $b['Name']];
});
var_export($array);

查看示例输入和输出的演示链接。

此 sn-p 将按以下方式排序:

  1. 生日 ASC 然后
  2. Hometown === CurrentLocation before not === then
  3. 命名 ASC

注意:#2 具有 !== 语法只是因为 false 评估被视为 0,true 评估被视为 1。

如果您需要更改任何条件的任何排序顺序,只需在相应元素处交换$a$b

【讨论】:

    【解决方案2】:

    更新

    我最近answered 这个问题在关于排序多维数组的“权威”主题中以一种更有能力的方式提出。您可以放心地跳过阅读此答案的其余部分,并直接点击链接以获得更强大的解决方案。

    原答案

    函数uasort 允许您定义自己的比较函数。只需将您想要的所有标准都放入其中。

    例如,先按生日再按姓名排序:

    function comparer($first, $second) {
        // First see if birthdays differ
        if ($first['birthday'] < $second['birthday']) {
            return -1;
        }
        else if ($first['birthday'] > $second['birthday']) {
            return 1;
        }
    
        // OK, birthdays are equal. What else?
        if ($first['name'] < $second['name']) {
            return -1;
        }
        else if ($first['name'] > $second['name']) {
            return 1;
        }
    
        // No more sort criteria. The two elements are equal.
        return 0;
    }
    

    我忽略了这样一个事实,即在您的示例中,生日不是可以通过使用运算符&lt; 进行简单比较来排序的格式。在实践中,您会先将它们转换为可简单比较的格式。

    更新:如果你认为维护一堆这些多标准比较器可能会很快变得丑陋,你会发现我同意。但是这个问题可以像计算机科学中的任何其他问题一样解决:只需添加另一个抽象级别。

    我将假设下一个示例使用 PHP 5.3,以便使用方便的匿名函数语法。但原则上,您可以对 create_function 执行相同的操作。

    function make_comparer() {
        $criteriaNames = func_get_args();
        $comparer = function($first, $second) use ($criteriaNames) {
            // Do we have anything to compare?
            while(!empty($criteriaNames)) {
                // What will we compare now?
                $criterion = array_shift($criteriaNames);
    
                // Do the actual comparison
                if ($first[$criterion] < $second[$criterion]) {
                    return -1;
                }
                else if ($first[$criterion] > $second[$criterion]) {
                    return 1;
                }
    
            }
    
            // Nothing more to compare with, so $first == $second
            return 0;
        };
    
        return $comparer;
    }
    

    你可以这样做:

    uasort($myArray, make_comparer('birthday', 'name'));
    

    这个例子可能太聪明了;一般来说,我不喜欢使用不接受名称参数的函数。但在这种情况下,使用场景是过于聪明的一个非常有力的论据。

    【讨论】:

      【解决方案3】:

      很好的问题。

      此伪代码来自您给出的问题的定义,旨在作为给uasort 的回调函数。我无法填写详细信息,因为您省略了您正在使用的代码;希望这会引导您走上正确的道路。

      function compare(p1, p2):
          if birthdays of p1 and p2 are not the same
              compare by birthday
          else
              compare by hometown
      

      如果有人能验证这是 cmets 中排序算法的有效比较函数,我将不胜感激。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-10-31
        • 1970-01-01
        • 2018-10-20
        • 1970-01-01
        • 2013-11-30
        • 1970-01-01
        相关资源
        最近更新 更多