PHP:如何使用usort按指定数组对含额外ID的多维数组排序
按指定数组顺序对带额外ID的多维数组排序(PHP)
需要根据指定数组$correct的顺序,对多维数组$sortme的键(ID)排序,但$sortme里存在不在$correct中的额外ID,常规排序逻辑失效。
示例数据
待排序多维数组:
$sortme = [ 10005 => [ 'odds' => [ 'a' => [ 'oda' => 1.230, 'odb' => 0.650 ] ] ], 10002 => [ 'odds' => [ 'a' => [ 'oda' => 2.0, 'odb' => 3.0 ] ] ], 10003 => [ 'odds' => [ 'a' => [ 'oda' => 4.0, 'odb' => 5.0 ] ] ], 20005 => [ // 不在指定顺序里的额外ID 'odds' => [ 'a' => [ 'oda' => 4.0, 'odb' => 5.0 ] ] ] ];
指定顺序数组:
$correct = [10003, 10002, 10005];
原代码的问题
你之前的代码逻辑完全错误:
- 遍历
$sortme时把$sortmee[$key]赋值成单个键值,再对这个单个值调用usort毫无意义(usort是用来排序数组的,单个值没法排序); - 根本没对
$sortme的键做排序,也没处理不在$correct里的额外ID。
原无效代码:
foreach ($sortme as $key => $value) { $sortmee[$key]=$key; $sort = function ($a, $b) use ($correct ) { return array_search($a, $correct ) - array_search($b, $correct ); }; usort($sortmee[$key], $sort); }
正确解决方法
用uksort(按数组键排序),先把$correct转成优先级映射数组提升效率,同时处理额外ID的排序位置:
// 把指定顺序数组转为键是ID、值是排序优先级的关联数组 $priorityMap = array_flip($correct); // 对$sortme的键进行排序 uksort($sortme, function($idA, $idB) use ($priorityMap) { // 两个ID都在指定顺序里:按优先级比较 if (isset($priorityMap[$idA]) && isset($priorityMap[$idB])) { return $priorityMap[$idA] - $priorityMap[$idB]; } // 只有一个ID在指定顺序里:让指定顺序内的排在前面 if (isset($priorityMap[$idA])) { return -1; } if (isset($priorityMap[$idB])) { return 1; } // 两个ID都不在指定顺序里:这里按ID升序排列,你也可以改成其他规则 return $idA - $idB; });
代码说明
- $priorityMap数组:用
array_flip反转$correct的键值,比如$correct[0] = 10003变成$priorityMap[10003] = 0,这样查ID的优先级直接通过键访问,比每次用array_search遍历数组快得多。 - uksort函数:专门针对数组的键排序,回调里的
$idA和$idB是$sortme的两个键,返回值决定顺序:- 负数:
$idA排在$idB前面; - 正数:
$idB排在$idA前面; - 0:顺序不变。
- 负数:
- 额外ID处理:如果ID不在
$priorityMap里,我们让指定顺序内的ID优先排在前面,不在的可以按ID大小排序(或者你需要的其他规则,比如放在最前面、保持原顺序等,改对应的返回值就行)。
最终排序结果
运行后$sortme的键顺序为:10003, 10002, 10005, 20005,完全符合预期。
内容的提问来源于stack exchange,提问作者C123D
相关产品推荐
相关产品推荐

