我有一个像这样的关联数组:
$all_works = [
["title"=>"A Children’s Story", "year"=>"2024"],
["title"=>"Occurred during the Day", "year"=>"2021"],
["title"=>"Future and Past", "year"=>"2021"],
["title"=>"Future and History", "year"=>"2020"],
["title"=>"Open the School, Close the Studio", "year"=>"2023"],
["title"=>"To Reconstruct, To Rebuild", "year"=>"2024"],
["title"=>"Eyeglasses, a Story", "year"=>"2023"],
["title"=>"Nomadic Life", "year"=>"2024"],
["title"=>"Chipotle!", "year"=>"2022"],
["title"=>"between Art & Technology", "year"=>"2020"],
["title"=>"interview Script", "year"=>"2018"],
["title"=>"memories and confession", "year"=>"2024"],
["title"=>"Guest of Pluto", "year"=>"2022"],
["title"=>"A Prologue", "year"=>"2022"],
["title"=>"You are in this place", "year"=>"2023"],
["title"=>"Happening Now", "year"=>"2024"],
["title"=>"Review Catalogue", "year"=>"2022"],
["title"=>"A living being of Mars", "year"=>"2021"],
];
我尝试按每个子数组的“年份”值的数字顺序对该数组进行排序,当“年份”值相同时,按“的自然字母数字顺序对子数组进行排序”标题”值。
所以这就是我所做的:
usort($all_works, function($work1, $work2) {
return $work2["year"] <=> $work1["year"];
});
echo "<br><br>";
echo "<pre>";
print_r($all_works);
echo "</pre>";
usort($all_works, function($work3, $work4){
if($work3["year"] == $work4["year"]){
return strnatcmp($work3["title"], $work4["title"]);
}else{
return 0;
}
});
echo "<br><br>";
echo "<pre>";
print_r($all_works);
echo “</pre>";
当我使用 php 8.2.0 运行这些代码时,它的工作效果完全符合我的预期。输出是:
Array
(
[0] => Array
(
[title] => A Children’s Story
[year] => 2024
)
[1] => Array
(
[title] => To Reconstruct, To Rebuild
[year] => 2024
)
[2] => Array
(
[title] => Nomadic Life
[year] => 2024
)
[3] => Array
(
[title] => memories and confession
[year] => 2024
)
[4] => Array
(
[title] => Happening Now
[year] => 2024
)
[5] => Array
(
[title] => Open the School, Close the Studio
[year] => 2023
)
[6] => Array
(
[title] => Eyeglasses, a Story
[year] => 2023
)
[7] => Array
(
[title] => You are in this place
[year] => 2023
)
[8] => Array
(
[title] => Chipotle!
[year] => 2022
)
[9] => Array
(
[title] => Guest of Pluto
[year] => 2022
)
[10] => Array
(
[title] => A Prologue
[year] => 2022
)
[11] => Array
(
[title] => Review Catalogue
[year] => 2022
)
[12] => Array
(
[title] => Occurred during the Day
[year] => 2021
)
[13] => Array
(
[title] => Future and Past
[year] => 2021
)
[14] => Array
(
[title] => A living being of Mars
[year] => 2021
)
[15] => Array
(
[title] => Future and History
[year] => 2020
)
[16] => Array
(
[title] => between Art & Technology
[year] => 2020
)
[17] => Array
(
[title] => interview Script
[year] => 2018
)
)
Array
(
[0] => Array
(
[title] => A Children’s Story
[year] => 2024
)
[1] => Array
(
[title] => Happening Now
[year] => 2024
)
[2] => Array
(
[title] => Nomadic Life
[year] => 2024
)
[3] => Array
(
[title] => To Reconstruct, To Rebuild
[year] => 2024
)
[4] => Array
(
[title] => memories and confession
[year] => 2024
)
[5] => Array
(
[title] => Eyeglasses, a Story
[year] => 2023
)
[6] => Array
(
[title] => Open the School, Close the Studio
[year] => 2023
)
[7] => Array
(
[title] => You are in this place
[year] => 2023
)
[8] => Array
(
[title] => A Prologue
[year] => 2022
)
[9] => Array
(
[title] => Chipotle!
[year] => 2022
)
[10] => Array
(
[title] => Guest of Pluto
[year] => 2022
)
[11] => Array
(
[title] => Review Catalogue
[year] => 2022
)
[12] => Array
(
[title] => A living being of Mars
[year] => 2021
)
[13] => Array
(
[title] => Future and Past
[year] => 2021
)
[14] => Array
(
[title] => Occurred during the Day
[year] => 2021
)
[15] => Array
(
[title] => Future and History
[year] => 2020
)
[16] => Array
(
[title] => between Art & Technology
[year] => 2020
)
[17] => Array
(
[title] => interview Script
[year] => 2018
)
)
但是,当我使用 php 7.4.33 运行完全相同的代码时,结果看起来非常随机(特别是第二个 usort 函数之后的数组输出,不仅“title”的字母数字顺序不起作用,而且“年”的数字顺序混乱)。这是结果:
Array
(
[0] => Array
(
[title] => A Children’s Story
[year] => 2024
)
[1] => Array
(
[title] => Happening Now
[year] => 2024
)
[2] => Array
(
[title] => To Reconstruct, To Rebuild
[year] => 2024
)
[3] => Array
(
[title] => Nomadic Life
[year] => 2024
)
[4] => Array
(
[title] => memories and confession
[year] => 2024
)
[5] => Array
(
[title] => Open the School, Close the Studio
[year] => 2023
)
[6] => Array
(
[title] => Eyeglasses, a Story
[year] => 2023
)
[7] => Array
(
[title] => You are in this place
[year] => 2023
)
[8] => Array
(
[title] => Guest of Pluto
[year] => 2022
)
[9] => Array
(
[title] => Review Catalogue
[year] => 2022
)
[10] => Array
(
[title] => Chipotle!
[year] => 2022
)
[11] => Array
(
[title] => A Prologue
[year] => 2022
)
[12] => Array
(
[title] => A living being of Mars
[year] => 2021
)
[13] => Array
(
[title] => Occurred during the Day
[year] => 2021
)
[14] => Array
(
[title] => Future and Past
[year] => 2021
)
[15] => Array
(
[title] => Future and History
[year] => 2020
)
[16] => Array
(
[title] => between Art & Technology
[year] => 2020
)
[17] => Array
(
[title] => interview Script
[year] => 2018
)
)
Array
(
[0] => Array
(
[title] => A Children’s Story
[year] => 2024
)
[1] => Array
(
[title] => Chipotle!
[year] => 2022
)
[2] => Array
(
[title] => Future and History
[year] => 2020
)
[3] => Array
(
[title] => between Art & Technology
[year] => 2020
)
[4] => Array
(
[title] => A living being of Mars
[year] => 2021
)
[5] => Array
(
[title] => Future and Past
[year] => 2021
)
[6] => Array
(
[title] => Occurred during the Day
[year] => 2021
)
[7] => Array
(
[title] => A Prologue
[year] => 2022
)
[8] => Array
(
[title] => Guest of Pluto
[year] => 2022
)
[9] => Array
(
[title] => Review Catalogue
[year] => 2022
)
[10] => Array
(
[title] => Happening Now
[year] => 2024
)
[11] => Array
(
[title] => Eyeglasses, a Story
[year] => 2023
)
[12] => Array
(
[title] => Open the School, Close the Studio
[year] => 2023
)
[13] => Array
(
[title] => You are in this place
[year] => 2023
)
[14] => Array
(
[title] => Nomadic Life
[year] => 2024
)
[15] => Array
(
[title] => To Reconstruct, To Rebuild
[year] => 2024
)
[16] => Array
(
[title] => memories and confession
[year] => 2024
)
[17] => Array
(
[title] => interview Script
[year] => 2018
)
)
我不确定发生了什么,甚至在 php 7.4.33 的结果中找不到任何逻辑或模式。
usort() 在 php 8.2.0 和 php 7.4.33 中的行为是否不同?
在这个例子中,php 7.4.33 到底在做什么,导致第二个结果看起来完全不合逻辑? (或者有逻辑但我没看到?)
在使用 php 7.4.33 时,我应该怎样做才能使我的代码像在 php 8.2.0 中一样工作?
(附加信息:我在 mac 上使用 MAMP 本地服务器运行我的代码,如果这很重要的话)。
来自手册:
注:
如果两个成员比较相等,则它们保留原来的顺序。在 PHP 8.0.0 之前,它们在排序数组中的相对顺序是未定义的。
您的问题是,对于比较相等的元素,第二种排序并不“稳定”。
要解决此问题,只需将排序逻辑移至单个函数中并仅排序一次:
usort($all_works, function($work1, $work2) {
$cmp = $work2["year"] <=> $work1["year"];
if($cmp == 0)
{
$cmp = strnatcmp($work1["title"], $work2["title"]);
}
return $cmp;
});
如前所述,PHP8 实现了稳定排序,之前的任何版本都没有承诺保留原始元素顺序。
至于清理代码,可以简化为以下内容:(Demo)
usort($all_works, fn($a, $b) => $a['year'] <=> $b['year'] ?: strnatcmp($a["title"], $b["title"]));
也可以使用
array_multisort()
来享受等效的行为:(演示)
array_multisort(
array_column($all_works, 'year'),
array_column($all_works, 'title'),
SORT_STRING | SORT_NATURAL,
$all_works
);