如何在JavaScript中扁平化数组时分组匹配的嵌套子数组?
问题描述
从API获取到一组汽车品牌数据,需要将其转换为带分组属性的扁平化格式:以汽车品牌(carMake)、轮胎尺寸(size)、轮胎宽度(width)作为分组依据,当这三个属性都匹配时合并记录,把对应轮胎品牌合并到一个数组中,同时保留其他关联字段。
原始API响应数据
[ { carMake: 'Ford', tires: [ { brand: 'Dunlap', otherKey: 'aaa', size: 33, width: 12, }, { brand: 'Good Year', size: 33, width: 12, }, { brand: 'Continental', size: 33, width: 11, }, { brand: 'Pirelli', size: 32, width: 12, } ] }, { carMake: 'Chevy', tires: [ { brand: 'Dunlap', size: 33, width: 12, }, ] } ]
期望转换结果
[ { carMake: 'Ford', otherKey: 'aaa', brands: ['Dunlap', 'Good Year'], size: 33, width: 12, }, { carMake: 'Ford', brands: ['Continental'], size: 33, width: 11, }, { carMake: 'Ford', brands: ['Pirelli'], size: 32, width: 12, }, { carMake: 'Chevy', brands: ['Dunlap'], size: 33, width: 12, } ]
已尝试的代码
仅完成了第一层扁平化,未实现分组合并:
apiResponse.flatMap(({carMake, tires}) => tires.map((tire) => ({ carMake, ...tire })));
解决方案
通过扁平化数据 → 分组聚合 → 格式化输出三步实现需求:
1. 扁平化数据
先把嵌套的轮胎数据展开,每条记录带上对应汽车品牌:
const flatData = apiResponse.flatMap(({ carMake, tires }) => tires.map(tire => ({ carMake, ...tire })) );
2. 分组聚合
用reduce方法,以carMake-size-width作为唯一分组键,合并同组的轮胎品牌,同时保留其他字段(取同组第一条记录的对应值):
const grouped = flatData.reduce((acc, item) => { // 生成唯一分组标识 const key = `${item.carMake}-${item.size}-${item.width}`; if (!acc[key]) { // 首次创建分组,初始化结构 acc[key] = { carMake: item.carMake, size: item.size, width: item.width, brands: [item.brand], // 仅当存在时保留额外字段 ...(item.otherKey && { otherKey: item.otherKey }) }; } else { // 已有分组,追加品牌到数组 acc[key].brands.push(item.brand); } return acc; }, {});
3. 转换为数组格式
将分组后的对象转为最终的数组结构:
const result = Object.values(grouped);
完整代码
const apiResponse = [ { carMake: 'Ford', tires: [{ brand: 'Dunlap', otherKey: 'aaa', size: 33, width: 12 }, { brand: 'Good Year', size: 33, width: 12 }, { brand: 'Continental', size: 33, width: 11 }, { brand: 'Pirelli', size: 32, width: 12 }] }, { carMake: 'Chevy', tires: [{ brand: 'Dunlap', size: 33, width: 12 }] } ]; const flatData = apiResponse.flatMap(({ carMake, tires }) => tires.map(tire => ({ carMake, ...tire })) ); const grouped = flatData.reduce((acc, item) => { const key = `${item.carMake}-${item.size}-${item.width}`; if (!acc[key]) { acc[key] = { carMake: item.carMake, size: item.size, width: item.width, brands: [item.brand], ...(item.otherKey && { otherKey: item.otherKey }) }; } else { acc[key].brands.push(item.brand); } return acc; }, {}); const result = Object.values(grouped); console.log(result);
内容的提问来源于stack exchange,提问作者WebDevz
相关产品推荐
相关产品推荐

