PHP - 多个uasort函数会破坏排序

时间:2011-03-04 19:22:19

标签: php arrays multidimensional-array sorting

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

Array (
   id93294 => (array (
             Name => "Tom Anderson",
             Birthday => "03/17/1975"),
   id29349 => (array (
             Name => "Tom Anderson",
             Birthday => "03/17/1975")
)

有点像那样,除了有更多的人的信息,所以我想先按生日排序然后按另一个属性排序(如果他们的家乡匹配他们的当前位置)但是一旦我在阵列上进行第二次排序,它就失去了我用生日那天做的第一次......

如何在不弄乱我以前的种类的情况下多次排序。

P.S。我正在使用uasort。

3 个答案:

答案 0 :(得分:6)

更新

我最近在关于排序多维数组的“权威”主题中以更有能力的方式提出了这个问题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;
}

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

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

我将为下一个示例假设PHP 5.3,以便使用方便的anon函数语法。但原则上,您可以对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'));

这个例子可能试图太聪明;一般来说,我不喜欢使用不接受名称参数的函数。但在这种情况下,使用场景是一个非常强烈的理由,因为它过于聪明。

答案 1 :(得分:1)

很棒的问题。

此伪代码来自您给出的问题的定义,并且旨在作为uasort的回调函数。我无法填写详细信息,因为您已经省略了您正在使用的代码;希望这能带领你走上正轨。

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

如果有人可以在评论中验证这是排序算法的有效比较函数,我将不胜感激。

答案 2 :(得分:0)

很多年后,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);

有关示例输入和输出,请参见演示链接。

此代码段的排序方式:

  1. 然后是生日ASC
  2. 家乡===当前位置,不先===然后
  3. 名称ASC

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

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

相关问题