如何将二维数组按子数组首元素分组?reduce用法存疑求助
问题分析与解决方案
首先看你的代码逻辑:它是把相邻且首元素相同的子数组归为一组,这个思路在输入数组已经按首元素排序、同组元素连续出现的情况下是可行的,但存在一个不严谨的地方——当循环到第一个元素(i=0)时,a[i-1]是undefined,虽然JS中c[0] != undefined会被判定为true,第一次循环能正常执行,但这种写法容易引发潜在问题,比如如果首元素本身是undefined的话就会出错。
优化你的原有思路(适用于输入已按首元素连续排列的场景)
可以加上i === 0的判断,避免访问不存在的数组索引:
const input = [[1, 'aaa'], [1, 'bbb'], [2, 'ccc'], [2, 'ddd']]; const output = input.reduce((r, c, i, a) => { if (i === 0 || c[0] !== a[i - 1][0]) { r.push([c]); } else { r[r.length - 1].push(c); } return r; }, []);
更通用的方案(适用于任意顺序的输入)
如果你的输入数组可能是乱序的,需要严格按首元素的值分组(不管位置),那原有思路就不适用了。推荐用对象或Map来实现分组,再提取结果:
方法1:使用Map
const input = [[1, 'aaa'], [1, 'bbb'], [2, 'ccc'], [2, 'ddd']]; const groupMap = new Map(); input.forEach(item => { const key = item[0]; // 不存在该分组则初始化 if (!groupMap.has(key)) { groupMap.set(key, []); } groupMap.get(key).push(item); }); // 将Map的值转为数组,得到最终结果 const output = Array.from(groupMap.values());
方法2:使用reduce+对象
const input = [[1, 'aaa'], [1, 'bbb'], [2, 'ccc'], [2, 'ddd']]; const output = Object.values(input.reduce((acc, item) => { const key = item[0]; acc[key] = acc[key] || []; acc[key].push(item); return acc; }, {}));
这两种方法不管输入是否有序,都能准确将首元素相同的子数组归为一组。
内容的提问来源于stack exchange,提问作者chrisbib
相关产品推荐
相关产品推荐

