首先,如果您的输入数组是 MySQL 查询的结果集,您应该通过 ORDER BY 子句对数据进行排序。 FIELD() 是一个出色的工作工具,有点奇怪,您需要反转排序逻辑并在函数后写 DESC。
资源:https://www.electrictoolbox.com/mysql-order-specific-field-values/(向下滚动到“gotcha”)
SQL 小提琴演示:http://sqlfiddle.com/#!9/6b996f/1
除此之外,我将提供 Nigel 和 Eddie 的解决方案的两个改进版本,它们利用了一些 php7+ 的优点。您选择实施哪一项将与:
- 是否要允许具有重复
id 值的元素“存活”该过程
- 对于您的实际项目数据(输入数组和自定义订单数组的大小),哪个执行效率更高
- 个人喜好(sn-ps 都可以合理地写成 3 到 5 行,所以简洁不是标准)
PHP Demo
$array = [
(object)['id' => 8],
(object)['id' => 7],
(object)['id' => 5]
];
$order = [5, 8, 1]; // custom sort order
$order = array_flip($order); // restructure for easy lookup with isset()
$order[''] = max(array_column($array, 'id')) + 1; // append value higher than max for outlying ids
usort($array, function($a, $b) use ($order) {
return ($order[$a->id] ?? $order['']) <=> ($order[$b->id] ?? $order['']);
});
var_export($array);
*请注意,我本可以将 $outlier 作为第二个 use 参数传递到自定义函数范围中,并将所有 $order[''] 变量替换为 $outlier,但我选择将异常数据附加到查找中数组。
*我在自定义函数中使用括号不仅是为了提高可读性,而且是为了保证评估按预期执行——我实际上并没有费心检查评估是否与括号分组相同。
(PHP Demo)
$array = [
(object)['id' => 8],
(object)['id' => 7],
(object)['id' => 5]
];
$order = [5, 8, 1];
$order = array_flip($order); // flip for future key comparisons
$keyed = array_column($array, null, 'id'); // declare id values as new keys
$filtered_order = array_intersect_key($order, $keyed); // remove unwanted order keys
$replaced = array_replace($filtered_order, $keyed); // apply objects to output array
var_export(array_values($replaced)); // re-index the output (if desired)
*请注意,这不会生成一个过大的 null 值数组,也不会删除“错误”的值。
*我再次声明,如果输入数组中有重复的id 值,使用array_column() 会损坏数据。