如何在Laravel中按question_id的唯一性对数组排序
需求说明
我有一个包含多个子数组的数组列表,每个子数组包含若干字段。需要基于question_id字段对该列表排序,要求每个question_id对应的首个出现的数组排在前面,重复的同question_id数组放在后面,且不删除任何数组元素。
原始数组
array:6 [▼ 0 => array:8 [▼ "id" => 35 "answer" => null "type" => 3 "user_id" => 9 "question_id" => 36 "answer_id" => 1 "created_at" => "2023-04-07T09:03:39.000000Z" "updated_at" => "2023-04-07T09:03:39.000000Z" ] 1 => array:8 [▼ "id" => 36 "answer" => null "type" => 3 "user_id" => 9 "question_id" => 36 "answer_id" => 1 "created_at" => "2023-04-07T09:03:39.000000Z" "updated_at" => "2023-04-07T09:03:39.000000Z" ] 2 => array:8 [▼ "id" => 37 "answer" => "Gello" "type" => 0 "user_id" => 9 "question_id" => 37 "answer_id" => 1 "created_at" => "2023-04-07T09:03:39.000000Z" "updated_at" => "2023-04-07T09:03:39.000000Z" ] 3 => array:8 [▼ "id" => 38 "answer" => "Uho" "type" => 0 "user_id" => 9 "question_id" => 37 "answer_id" => 1 "created_at" => "2023-04-07T09:03:39.000000Z" "updated_at" => "2023-04-07T09:03:39.000000Z" ] 4 => array:8 [▼ "id" => 39 "answer" => "Who" "type" => 1 "user_id" => 9 "question_id" => 38 "answer_id" => 1 "created_at" => "2023-04-07T09:03:39.000000Z" "updated_at" => "2023-04-07T09:03:39.000000Z" ] 5 => array:8 [▼ "id" => 40 "answer" => "Window" "type" => 1 "user_id" => 9 "question_id" => 38 "answer_id" => 1 "created_at" => "2023-04-07T09:03:40.000000Z" "updated_at" => "2023-04-07T09:03:40.000000Z" ] ]
期望排序后的数组
array:6 [▼ 0 => array:8 [▼ "id" => 35 "answer" => null "type" => 3 "user_id" => 9 "question_id" => 36 "answer_id" => 1 "created_at" => "2023-04-07T09:03:39.000000Z" "updated_at" => "2023-04-07T09:03:39.000000Z" ] 2 => array:8 [▼ "id" => 37 "answer" => "Hello" "type" => 0 "user_id" => 9 "question_id" => 37 "answer_id" => 1 "created_at" => "2023-04-07T09:03:39.000000Z" "updated_at" => "2023-04-07T09:03:39.000000Z" ] 4 => array:8 [▼ "id" => 39 "answer" => "Who" "type" => 1 "user_id" => 9 "question_id" => 38 "answer_id" => 1 "created_at" => "2023-04-07T09:03:39.000000Z" "updated_at" => "2023-04-07T09:03:39.000000Z" ] 1 => array:8 [▼ "id" => 36 "answer" => null "type" => 3 "user_id" => 9 "question_id" => 36 "answer_id" => 1 "created_at" => "2023-04-07T09:03:39.000000Z" "updated_at" => "2023-04-07T09:03:39.000000Z" ] 3 => array:8 [▼ "id" => 38 "answer" => "Uho" "type" => 0 "user_id" => 9 "question_id" => 37 "answer_id" => 1 "created_at" => "2023-04-07T09:03:39.000000Z" "updated_at" => "2023-04-07T09:03:39.000000Z" ] 5 => array:8 [▼ "id" => 40 "answer" => "Window" "type" => 1 "user_id" => 9 "question_id" => 38 "answer_id" => 1 "created_at" => "2023-04-07T09:03:40.000000Z" "updated_at" => "2023-04-07T09:03:40.000000Z" ] ]
实现方案(PHP)
推荐采用分组重组的方式,逻辑简单且效率较高:
- 遍历原始数组,将每个
question_id的首个元素单独收集,重复元素按question_id分组存储 - 先将所有首个元素按原始顺序排列,再依次追加每个
question_id的重复元素
代码示例:
// 原始数组,替换为你的数组变量 $originalArray = [ ["id" => 35, "answer" => null, "type" => 3, "user_id" => 9, "question_id" => 36, "answer_id" => 1, "created_at" => "2023-04-07T09:03:39.000000Z", "updated_at" => "2023-04-07T09:03:39.000000Z"], ["id" => 36, "answer" => null, "type" => 3, "user_id" => 9, "question_id" => 36, "answer_id" => 1, "created_at" => "2023-04-07T09:03:39.000000Z", "updated_at" => "2023-04-07T09:03:39.000000Z"], ["id" => 37, "answer" => "Gello", "type" => 0, "user_id" => 9, "question_id" => 37, "answer_id" => 1, "created_at" => "2023-04-07T09:03:39.000000Z", "updated_at" => "2023-04-07T09:03:39.000000Z"], ["id" => 38, "answer" => "Uho", "type" => 0, "user_id" => 9, "question_id" => 37, "answer_id" => 1, "created_at" => "2023-04-07T09:03:39.000000Z", "updated_at" => "2023-04-07T09:03:39.000000Z"], ["id" => 39, "answer" => "Who", "type" => 1, "user_id" => 9, "question_id" => 38, "answer_id" => 1, "created_at" => "2023-04-07T09:03:39.000000Z", "updated_at" => "2023-04-07T09:03:39.000000Z"], ["id" => 40, "answer" => "Window", "type" => 1, "user_id" => 9, "question_id" => 38, "answer_id" => 1, "created_at" => "2023-04-07T09:03:40.000000Z", "updated_at" => "2023-04-07T09:03:40.000000Z"], ]; $firstItems = []; $duplicateGroups = []; foreach ($originalArray as $item) { $qid = $item['question_id']; if (!isset($duplicateGroups[$qid])) { // 首次出现的元素加入单独列表 $firstItems[] = $item; $duplicateGroups[$qid] = []; } else { // 重复元素加入对应分组 $duplicateGroups[$qid][] = $item; } } // 合并得到排序后的数组:先首个元素,再各分组的重复元素 $sortedArray = array_merge($firstItems, ...array_values($duplicateGroups)); // 输出结果 print_r($sortedArray);
方案说明
- 该方法时间复杂度为O(n),仅需遍历一次原始数组,效率远高于排序函数多次比较的方式
- 严格保留了原始数组中
question_id的首次出现顺序,以及重复元素的原始顺序
内容的提问来源于stack exchange,提问作者Amirali Pourmoshir
相关产品推荐
相关产品推荐

