JS重排数组元素 实现相同key对象不相邻排列
数组重排需求说明
- 输入:所有元素均为单key对象的数组
myArray - 排序规则:
- 优先调整元素位置,尽可能保证相邻两个对象的key不重复
- 若某类key的元素总数超过数组长度的1/2,无法实现完全间隔排列时,剩余的同key元素统一追加到数组末尾
- 参考期望效果(以
morning/evening两类key为例):
const finalArray = [ {"morning": "..."}, {"evening": "..."}, {"morning": "..."}, {"evening": "..."}, {"morning": "..."}, {"evening": "..."}, {"morning": "..."}, {"evening": "..."}, {"evening": "..."}, {"evening": "..."} ]
原有代码问题分析
原有实现存在3个核心缺陷,是导致排序中途混乱的根本原因:
- 未提前按key对元素做分组统计,直接按原数组遍历顺序判断插入,也没有优先安排元素数量最多的key,很容易提前耗尽数量少的key,导致大量同key元素提前堆积
- 存在重复插入逻辑漏洞:首个元素初始化插入
orderedArray后,后续遍历key的逻辑没有跳过该元素,会触发重复判断、重复插入 - 放入
unOrderedArray的元素未做二次校验,直接拼接时可能出现拼接位置前后key相同的问题
正确实现方案
核心实现逻辑:先按key对所有元素分组,每次插入元素时,优先选择和上一个插入元素key不同、且剩余元素数量最多的分组取元素插入,直到找不到符合间隔要求的元素,再把所有剩余元素统一追加到数组末尾。
const myArray = [{ "morning": "23_6557" }, { "evening": "7665_908" }, { "evening": "545_787" }, { "evening": "8774_957" }, { "morning": "434_6447" }, { "morning": "775_67" }, { "evening": "4554_8774" }, { "evening": "224_74" }, { "evening": "43_112" }, { "morning": "32_47" }] function rearrangeArray(arr) { // 按key对元素分组 const groupMap = new Map() arr.forEach(item => { const key = Object.keys(item)[0] if (!groupMap.has(key)) groupMap.set(key, []) groupMap.get(key).push(item) }) // 分组按剩余元素数量降序排序 let groups = Array.from(groupMap.entries()) .map(([key, list]) => ({key, list})) .sort((a, b) => b.list.length - a.list.length) const result = [] let lastKey = null while (groups.length) { // 查找第一个符合间隔要求的非空分组 const targetIndex = groups.findIndex(group => group.key !== lastKey && group.list.length) // 找不到可间隔插入的元素,终止循环 if (targetIndex === -1) break // 取出元素插入结果集 const targetGroup = groups[targetIndex] result.push(targetGroup.list.shift()) lastKey = targetGroup.key // 过滤空分组,重新按剩余数量排序 groups = groups.filter(group => group.list.length) .sort((a, b) => b.list.length - a.list.length) } // 拼接剩余无法间隔插入的元素 const rest = groups.flatMap(group => group.list) return [...result, ...rest] } const finalArray = rearrangeArray(myArray) console.log(finalArray)
针对给出的测试用例,上述代码运行后会输出完全符合预期的结果:前8位交替排列morning和evening类元素,剩余2个evening类元素追加在末尾,不会出现相邻同key的排序混乱问题。
内容的提问来源于stack exchange,提问作者seriously
相关产品推荐
相关产品推荐

