我有一个存储人的多维数组。
Array (
id93294 => (array (
Name => "Tom Anderson",
Birthday => "03/17/1975"),
id29349 => (array (
Name => "Tom Anderson",
Birthday => "03/17/1975")
)
有点像那样,除了有更多的人的信息,所以我想先按生日排序然后按另一个属性排序(如果他们的家乡匹配他们的当前位置)但是一旦我在阵列上进行第二次排序,它就失去了我用生日那天做的第一次......
如何在不弄乱我以前的种类的情况下多次排序。
P.S。我正在使用uasort。
答案 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);
有关示例输入和输出,请参见演示链接。
此代码段的排序方式:
注意:#2之所以具有!==
语法,是因为false
的评估被视为0,而true
的评估被视为1。
如果您需要更改任何条件的任何排序顺序,只需在相应的元素处交换$a
和$b
。