JavaScript不使用flatMap将子数组展开为父属性实现数组扁平化
数组扁平化转换问题
需求背景
已完成数据分组操作,需要将分组后的数据转换为扁平结构。
源数据
data = [ { "Name":"Gorba Technology", "Product":"Dell", "City":[ "Delhi", "Mumbai" ] }, { "Name":"Suvidha Computer", "Product":"Lenovo", "City":[ "Deoghar" ] }, { "Name":"Sara Laptop", "Product":"Dell", "City":[ "Noida", "Delhi" ] } ]
期望输出
拆分每条记录的City数组,每个城市对应一条仅包含Name、City字段的扁平记录,结构如下:
[ {"Name":"Gorba Technology","City":"Delhi"}, {"Name":"Gorba Technology","City":"Mumbai"}, {"Name":"Suvidha Computer","City":"Deoghar"}, {"Name":"Sara Laptop","City":"Noida"}, {"Name":"Sara Laptop","City":"Delhi"} ]
已尝试方案与限制
- 曾尝试嵌套
map实现,未得到预期结果,代码如下:
var result = data.map(({Name, City}) => City.map(item => {Name, item}));
- 使用
flatMap实现会触发lint报错,要求*不使用flatMap*完成上述扁平化转换。
解决方案
原有写法存在两个问题:
- 两层
map执行后返回的是二维数组,未做扁平化处理 - 内层箭头函数直接写
{Name, item}时,大括号会被JS解析为函数体标记,不会识别为待返回对象;同时返回对象的City字段未明确指定键名,不符合输出要求。
以下提供两种不依赖flatMap的可运行实现:
写法1:map + concat 打平
利用concat可以合并数组的特性,将map生成的二维数组打平为一维:
var result = [].concat.apply([], data.map(({Name, City}) => // 箭头函数返回对象必须用括号包裹,明确指定City字段的键值 City.map(cityItem => ({Name, City: cityItem})) ));
写法2:reduce 遍历累加
通过reduce直接遍历累加生成一维数组,逻辑更直观:
var result = data.reduce((acc, current) => { // 遍历当前项的所有城市,逐个推入结果数组 current.City.forEach(cityItem => { acc.push({ Name: current.Name, City: cityItem }) }) return acc; }, []); // 初始值传空数组
两种写法执行后输出结果和预期完全一致。
内容的提问来源于stack exchange,提问作者ANAND
相关产品推荐
相关产品推荐

