简体   繁体   English

按日期列对多维数组进行排序,如果日期相同则使用其他列值

[英]Sort multidimensional array by date column, then use other column values if dates are the same

I have a multidimensional array that stores people.我有一个存储人的多维数组。

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'
   )
)

Kind of like that except with more info for the people, so I want to first sort by birthdays THEN sort by another attribute (if their hometown matches their current location) but once I do the second sort on the array it loses the first sort I did using the birthdays...有点像,除了为人们提供更多信息,所以我想首先按生日排序然后按另一个属性排序(如果他们的家乡与他们当前的位置匹配)但是一旦我对数组进行第二次排序,它就会失去我的第一次排序确实使用了生日...

How do I sort multiple times without it messing up my previous sorts.我如何多次排序而不会弄乱我以前的排序。

PS I am using uasort. PS我正在使用uasort。

Update更新

I recently answered this question in a much more capable manner in the "definitive" topic on sorting multidimensional arrays.我最近在关于对多维数组进行排序的“确定性”主题中以更有能力的方式回答了这个问题。 You can safely skip reading the rest of this answer and directly follow the link for a much more capable solution.您可以安全地跳过阅读本答案的其余部分,并直接按照链接获取更强大的解决方案。

Original answer原答案

The function uasort lets you define your own comparison function.函数uasort允许您定义自己的比较函数。 Simply put all the criteria you want inside that.只需将您想要的所有标准放入其中。

For example, to sort by birthday and then by name:例如,要先按生日然后按姓名排序:

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

I am ignoring the fact that in your example, the birthdays are not in a format that can be ordered by a simple comparison using the operator < .我忽略了这样一个事实,即在您的示例中,生日不是可以通过使用运算符<进行简单比较来排序的格式。 In practice you would convert them to a trivially-comparable format first.在实践中,您首先会将它们转换为简单可比的格式。

Update: if you think that maintaining a bunch of these multiple-criteria comparers could get ugly real fast, you find me in agreement.更新:如果你认为维护一堆这些多标准比较器会很快变得丑陋,你会发现我同意。 But this problem can be solved as any other in computer science: just add another level of abstraction.但是这个问题可以像计算机科学中的任何其他问题一样解决:只需添加另一个抽象级别。

I 'll be assuming PHP 5.3 for the next example, in order to use the convenient anon function syntax.我将在下一个示例中假设 PHP 5.3,以便使用方便的 anon 函数语法。 But in principle, you could do the same with create_function .但原则上,你可以用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;
}

You could then do:然后你可以这样做:

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

This example possibly tries to be too clever;这个例子可能太聪明了; in general I don't like to use functions that do not accept their arguments by name.一般来说,我不喜欢使用不按名称接受参数的函数。 But in this case, the usage scenario is a very strong argument for being too clever.但在这种情况下,使用场景是过于聪明的一个非常有力的论据。

Excellent question.很好的问题。

This pseudo-code comes from the definition of the problem you gave and is intended to be the callback function given to uasort .此伪代码来自您给出的问题的定义,旨在成为提供给uasort的回调函数。 I cannot fill in the details because you've omitted the code you're using;我无法填写详细信息,因为您省略了正在使用的代码; hopefully this leads you on the right track.希望这会引导您走上正轨。

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

If someone could verify that this is a valid comparison function for a sort algorithm in the comments, I would be grateful.如果有人可以验证这是评论中排序算法的有效比较函数,我将不胜感激。

Many years later, there is a cleaner, more succinct technique provided from PHP7+ ...the spaceship operator and balanced arrays of "criteria".许多年后,PHP7+ 提供了一种更简洁、更简洁的技术……飞船操作符和“标准”的平衡数组。

Code: ( 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);

See the demo link for sample input and the output.请参阅示例输入和输出的演示链接。

This snippet will sort by:此代码段将按以下顺序排序:

  1. Birthday ASC then然后生日 ASC
  2. Hometown === CurrentLocation before not === then家乡 === CurrentLocation 之前没有 === 然后
  3. Name ASC名称 ASC

Note: #2 has !== syntax only because false evaluation are treated as 0 and true evaluations are treated as 1.注意:#2 有!==语法只是因为false评估被视为 0,而true评估被视为 1。

If you need to change any of the sorting orders for any of the criteria, just swap the $a and $b at the corresponding elements.如果您需要更改任何条件的任何排序顺序,只需在相应元素处交换$a$b

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM