JavaScript实现无序名称数组按指定交错规律重排
问题重述
给定无序名称数组示例:
let names = ['Jewel', 'Crown', 'Rob', 'Rob', 'Jewel', 'Crown']
需要将数组重排为同名称元素按固定顺序循环穿插的结果,示例输出如下:
['Jewel', 'Crown', 'Rob', 'Jewel', 'Crown', 'Rob']
要求实现一个接收无序名称数组的函数,返回符合上述排列规律的结果,提问者最初计划使用JavaScript的.filter方法实现,但未梳理出可行逻辑。
实现思路
首先明确核心排列规则:按元素首次出现的固定顺序做轮询填充——即先按顺序排所有不同名称的第一个元素,再按同样顺序排所有不同名称的第二个元素,以此类推,直到所有元素排列完成。
单靠一个.filter方法无法直接完成全流程逻辑,.filter的定位是按条件筛选元素,不支持跨元素组的位置调度,但可以将.filter用在元素分组环节,配合轮询逻辑实现需求:
- 第一步:提取所有不重复名称的序列,顺序取每个名称在原数组中第一次出现的顺序,和示例排序基准对齐
- 第二步:对每个名称,用
.filter从原数组中筛出所有同名元素,组成各自的待排列队列 - 第三步:按不重复名称的固定序列循环遍历,每轮遍历到某个名称时,就从它对应的待排队列头部取出一个元素放到结果数组中,直到所有队列的元素都被取完即可。
可运行代码实现
基础通用版本
function rearrangeNames(names) { // 用Map存储每个名称的待排队列,Map天然保留键的插入顺序(即名称首次出现的顺序) const nameQueues = new Map(); for (const name of names) { if (!nameQueues.has(name)) nameQueues.set(name, []); nameQueues.get(name).push(name); } const result = []; // 轮询取元素直到所有元素排完 while (result.length < names.length) { for (const [, queue] of nameQueues) { if (queue.length) result.push(queue.shift()); } } return result; } // 测试示例 const testArr = ['Jewel', 'Crown', 'Rob', 'Rob', 'Jewel', 'Crown']; console.log(rearrangeNames(testArr)); // 输出: ['Jewel', 'Crown', 'Rob', 'Jewel', 'Crown', 'Rob']
结合.filter的实现版本
如果你需要在实现中用到计划的.filter方法,可以参考下面的写法:
function rearrangeNamesWithFilter(names) { // 提取按首次出现顺序排列的唯一名称序列 const uniqueOrder = [...new Set(names)]; // 用filter为每个名称筛选出对应的待排队列 const nameQueues = uniqueOrder.map(name => names.filter(item => item === name)); const result = []; while (result.length < names.length) { nameQueues.forEach(queue => { if (queue.length) result.push(queue.shift()); }); } return result; }
补充说明
- 如果你的名称排列顺序是固定优先级(比如不管原数组里元素怎么出现,都要严格按Jewel→Crown→Rob的顺序轮询),直接把代码里的
uniqueOrder替换成固定的顺序数组即可 - 上述实现天然兼容不同名称出现次数不一致的场景,比如输入
['Rob', 'Rob', 'Rob', 'Jewel', 'Crown'],输出会是['Rob', 'Jewel', 'Crown', 'Rob', 'Rob'],符合轮询逻辑
内容的提问来源于stack exchange,提问作者JustTrynnaLearn
相关产品推荐
相关产品推荐

