[英]PHP How to sort an array of objects based on priority order with a backup of alphabetical?
我有一个这样的数组:
$sort_me = array(
array("file"=>"Desert.jpg"),
array("file"=>"Hello.jpg"),
array("file"=>"Test.jpg)
)
我想根据文件属性按字母顺序对这个数组进行排序。 为了使事情复杂化,我有一个可选数组:
$sort_order = array("Test.jpg", "Hello.jpg", "NotFound.jpg")
该数组将指定一些用户定义的排序。 这些数组元素具有优先级,如果找到它们将按该顺序放置。 与$sort_order
中的任何内容不匹配的其他元素应按字母顺序排列在数组的末尾。
In javascript I would use call a sort function with a comparator function that takes 2 elements and returns a number to place the first object ahead or behind the second.
如何使用 PHP 做到这一点?
编辑
我尝试了一些东西,但没有成功。 (再次修改,将逻辑放到一个function中,并概括按哪个字段排序)
<?php
function sort_priority($sort_me, $sort_order, $field) {
function compare($a, $b) {
if ($sort_order) {
$ai = array_search($a[$field], $sort_order);
$bi = array_search($b[$field], $sort_order);
if ($ai !== false && $bi === false) {
return -1;
} else if ($bi !== false && $ai === false) {
return 1;
} else if ($ai !== false && $bi !== false) {
return $bi - $ai;
}
}
return $a[$field] < $b[$field] ? -1 : 1;
}
usort($sort_me, "compare");
}
$sort_order = array("Test.jpg", "Hello.jpg", "NotFound.jpg");
$sort_me = array(
array("file"=>"Test.jpg"),
array("file"=>"Desert.jpg"),
array("file"=>"Hello.jpg")
);
sort_priority($sort_me, $sort_order, "file");
echo json_encode($sort_me);
?>
这输出
Notice: Undefined variable: sort_order in c:\workspace\test.php on line 10
预期的 output 是
[{"file":"Test.jpg"},{"file":"Hello.jpg"},{"file":"Desert.jpg"}]
我不知道如何compare
function 以正确使用特定于上下文的$sort_order
function。
编辑
我接受了一个答案,但为了完整起见,我想发布我最终得到的似乎可行的内容。 如果有人想发布更优雅的解决方案,我会考虑将其标记为已接受。 但这是我所拥有的:
<?php
function compare_priority($a, $b) {
global $g_order, $g_field;
if ($g_order) {
$ai = array_search($a[$g_field], $g_order);
$bi = array_search($b[$g_field], $g_order);
if ($ai !== false && $bi === false) {
return -1;
} else if ($bi !== false && $ai === false) {
return 1;
} else if ($ai !== false && $bi !== false) {
return $ai - $bi;
}
}
return $a[$g_field] < $b[$g_field] ? -1 : 1;
}
function sort_priority(&$sort_me, $sort_order, $field) {
global $g_order, $g_field;
$g_order = $sort_order;
$g_field = $field;
usort($sort_me, "compare_priority");
}
$sort_me = array(
array("file"=>"Z"),
array("file"=>"A"),
array("file"=>"Y"),
array("file"=>"B")
);
$sort_order = array("Z", "Y", "C");
sort_priority($sort_me, $sort_order, "file");
echo json_encode($sort_me);
?>
您可以像使用 javascript 一样做同样的事情。 usort ( http://ch2.php.net/manual/en/function.usort.php ) 允许您定义元素之间的自定义比较。
我修改了你的代码,它似乎工作:
<?php
function test() {
$sort_me = array(
array("file"=>"Test.jpg"),
array("file"=>"Desert.jpg"),
array("file"=>"Hello.jpg")
);
global $sort_order;
$sort_order = array("Test.jpg" , "Hello.jpg", "NotFound.jpg");
function compare($a, $b) {
global $sort_order;
if (is_array($sort_order)) {
$ai = array_search($a["file"], $sort_order);
$bi = array_search($b["file"], $sort_order);
if ($ai !== false && $bi === false) {
return -1;
} else if ($bi !== false && $ai === false) {
return 1;
} else if ($ai !== false && $bi !== false) {
return $ai - $bi;
}
}
return $a["file"] < $b["file"] ? -1 : 1;
}
usort($sort_me, "compare");
echo json_encode($sort_me);
}
test();
?>
对于具有较少函数调用的最干净的脚本,请将usort()
与 spaceship 运算符一起使用。
我遵循的技术遵循两步逻辑(包含条件的第一步):
样本输入:
$sort_me = [
["file" => "Desert.jpg"],
["file" => "What.jpg"],
["file" => "Hello.jpg"],
["file" => "Test.jpg"],
["file" => "Goodness.jpg"],
];
$sort_order = ["Test.jpg", "Hello.jpg", "NotFound.jpg"];
处理代码:(演示)
$lookup = array_flip($sort_order);
$fallback = count($sort_order);
usort($sort_me, function($a, $b) use ($lookup, $fallback) {
return [$lookup[$a['file']] ?? $fallback, $a['file']]
<=>
[$lookup[$b['file']] ?? $fallback, $b['file']];
});
var_export($sort_me);
输出:
array (
0 =>
array (
'file' => 'Test.jpg',
),
1 =>
array (
'file' => 'Hello.jpg',
),
2 =>
array (
'file' => 'Desert.jpg',
),
3 =>
array (
'file' => 'Goodness.jpg',
),
4 =>
array (
'file' => 'What.jpg',
),
)
从 PHP7.4 开始,您可以使用箭头函数语法将全局变量引入自定义函数的作用域中,而无需use()
声明。
usort($sort_me, fn($a, $b) =>
[$lookup[$a['file']] ?? $fallback, $a['file']]
<=>
[$lookup[$b['file']] ?? $fallback, $b['file']]
);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.