如何在不移动lock>0行的前提下按score和strtotime排序PHP数组
PHP数组排序:锁定元素固定位置,其余按规则排序
需求明确:
- 数组中
lock值大于0的元素,必须保持原始位置不动 - 剩余
lock=0的元素,先按score从小到大排序;若score相同,再按strtotime从小到大排序
输入数组
$array = [ ['id' => 7867867, 'lock' => 0, 'score' => 322, 'strtotime' => 16614713], ['id' => 7867867, 'lock' => 0, 'score' => 444, 'strtotime' => 16614613], ['id' => 7867867, 'lock' => 3, 'score' => 0, 'strtotime' => 16613713], ['id' => 7867867, 'lock' => 0, 'score' => 11, 'strtotime' => 16612713], ['id' => 7867867, 'lock' => 5, 'score' => 0, 'strtotime' => 16614413], ['id' => 7867867, 'lock' => 0, 'score' => 42, 'strtotime' => 16614113], ['id' => 7867867, 'lock' => 0, 'score' => 22, 'strtotime' => 16614013], ];
现有代码的问题
直接使用usort会让所有元素参与排序,包括锁定元素,导致它们的位置被打乱;另外原代码还错误地用对象语法->访问关联数组,会触发报错:
usort($array, function ($a, $b) { if ( $a->score == $b->score ) { return $b->strtotime <=> $a->strtotime; } return $b->score <=> $a->score; });
期望输出
[ ['id' => 7867867, 'lock' => 0, 'score' => 11, 'strtotime' => 16612713], ['id' => 7867867, 'lock' => 0, 'score' => 22, 'strtotime' => 16614013], ['id' => 7867867, 'lock' => 3, 'score' => 0, 'strtotime' => 16613713], ['id' => 7867867, 'lock' => 0, 'score' => 42, 'strtotime' => 16614113], ['id' => 7867867, 'lock' => 5, 'score' => 0, 'strtotime' => 16614413], ['id' => 7867867, 'lock' => 0, 'score' => 322, 'strtotime' => 16614713], ['id' => 7867867, 'lock' => 0, 'score' => 444, 'strtotime' => 16614613], ]
解决方案
不能直接全量排序,需拆分处理:
- 提取所有
lock=0的元素,单独按规则排序 - 遍历原数组,遇到锁定元素直接保留;遇到未锁定元素,用排序好的列表依次填充
完整代码:
// 1. 提取未锁定元素并按规则排序 $unlocked = array_filter($array, function($item) { return $item['lock'] == 0; }); usort($unlocked, function($a, $b) { // 先按score升序,score相同则按strtotime升序 if ($a['score'] !== $b['score']) { return $a['score'] <=> $b['score']; } return $a['strtotime'] <=> $b['strtotime']; }); // 重置索引,方便后续逐个取出 $unlocked = array_values($unlocked); $index = 0; // 2. 重新构建结果数组 $result = []; foreach ($array as $item) { if ($item['lock'] > 0) { // 锁定元素保留原位置 $result[] = $item; } else { // 未锁定元素用排序后的列表填充 $result[] = $unlocked[$index++]; } } // 输出结果 print_r($result);
这段代码会严格保留lock>0元素的原始位置,同时让未锁定元素按规则填充到剩余位置,完全符合需求。
内容的提问来源于stack exchange,提问作者Jack co
相关产品推荐
相关产品推荐

