如何将数组按Chemistry对象以3个元素间隔重新排列?
解决方案:拆分+分段插入
直接把原数组拆成两类元素分开处理,比嵌套循环逻辑清晰得多,不会绕晕:
- 先拆分元素
把原数组里的非Chemistry元素和Chemistry元素分开,各自保留原顺序:
// 提取所有非Chemistry科目 const nonChem = subjects.filter(item => item.subject !== 'Chemistry'); // 提取所有Chemistry科目 const chems = subjects.filter(item => item.subject === 'Chemistry');
- 按规则合并数组
用一个循环遍历非Chemistry数组,每取3个元素就插入一个Chemistry元素,直到其中一类元素耗尽:
const newSubjects = []; let chemPos = 0; // 记录当前用到第几个Chemistry元素 for (let i = 0; i < nonChem.length; i += 3) { // 截取当前3个非Chemistry元素 const batch = nonChem.slice(i, i + 3); newSubjects.push(...batch); // 如果还有剩余的Chemistry元素,插入一个 if (chemPos < chems.length) { newSubjects.push(chems[chemPos]); chemPos++; } } // 处理剩下的Chemistry元素(如果非Chem元素先用完了) while (chemPos < chems.length) { newSubjects.push(chems[chemPos]); chemPos++; }
为什么这个方法比嵌套循环靠谱?
之前嵌套循环出问题大概率是因为插入元素后数组长度变化,或者内层循环的索引没控制好,导致重复插入或者漏插。拆分后分开处理,两类元素的索引都是独立的,逻辑一目了然,还能完美保留原数组里元素的顺序。
如果你的需求是每隔3个元素(包括之前插入的Chemistry)就插一个,那逻辑稍微调整下:每次往新数组加元素,每加3个就检查有没有Chemistry元素可以插。代码大概是这样:
const newSubjects = []; const chems = subjects.filter(item => item.subject === 'Chemistry'); const nonChem = subjects.filter(item => item.subject !== 'Chemistry'); let chemPos = 0; let count = 0; // 先处理非Chem元素,每加3个插一个Chem for (const item of nonChem) { newSubjects.push(item); count++; if (count % 3 === 0 && chemPos < chems.length) { newSubjects.push(chems[chemPos]); chemPos++; count++; // 插入的Chem也算入计数 } } // 处理剩余Chem元素 while (chemPos < chems.length) { newSubjects.push(chems[chemPos]); chemPos++; }
你可以根据实际需求选上面两种逻辑中的一种。
内容的提问来源于stack exchange,提问作者yusufff
相关产品推荐
相关产品推荐

