JavaScript如何从嵌套对象数组提取指定id对应的data值
我有一个名为originalArrayData的数组,结构如下所示:
展开后结构如下:
该数组的每一项都是对象,对象内包含多个子对象,数组前几项的内容示例如下:
originalArrayData = [{ "16": { "id": 22, "grid_row_id": 5, "grid_col_id": 16, "data": "10", "created_at": "rertte", "error_mgs": null }, "header": "Row 2", "id": 5 }, { "17": { "id": 31, "grid_row_id": 9, "grid_col_id": 17, "data": "14", "created_at": "rtyhtyjtdyj", "error_mgs": null }, "header": "Row 1", "id": 6 }, { "18": { "id": 35, "grid_row_id": 9, "grid_col_id": 12, "data": "55", "created_at": "thrtuhrs", "error_mgs": null }, "header": "Row 1", "id": 6 } // ...更多项 ]
现有一个存储目标id的数组arrayOfIds,其中的数字为随机值,元素数量不固定,可能为1个、3个或更多,示例值如下:
arrayOfIds: [16 , 17]
需求:遍历数组,只要任意子对象的grid_col_id属性值存在于arrayOfIds中,就提取该对象的data属性值,存入独立的新数组。
已知提取数组中每个外层对象id属性的代码如下,运行结果为[5,6,7,8,9],无法满足当前需求:
let data = this.arrayList.map((obj) => obj.id);
目前尝试编写的代码运行后抛出错误:TypeError: row.forEach is not a function,错误代码如下:
var targetArr = [] this.originalArrayData.forEach(item=> { item.forEach(ins => { if(arrayOfIds.includes(ins.grid_col_id) targetArr.push(ins.data) }) })
目标输出结果为:[10, 14, ...],结果中包含10和14的原因是:originalArrayData中grid_col_id属于arrayOfIds:[16,17]的子对象,对应的data值分别为10和14,需要将这些值提取后存入新数组。
报错核心原因:originalArrayData的每一项item是普通对象,不是数组,无法直接调用forEach遍历。数组项的属性分为两类:一类是固定属性(比如header、id),另一类是key为数字字符串的格子对象(比如key为"16"、"17"、"18"的属性),需要遍历的是后者。
注意:如果你的运行环境不支持ES2019新增的flatMap方法,优先选择普通循环写法,兼容性更好。
方法1:简洁写法(支持flatMap的现代环境)
遍历外层数组,取出每个外层对象的所有属性值,过滤掉非格子类型的属性,匹配目标id后提取data字段:
const targetArr = this.originalArrayData.flatMap(item => { return Object.values(item).filter(subItem => { return subItem && typeof subItem === 'object' && arrayOfIds.includes(subItem.grid_col_id) }).map(matchedItem => matchedItem.data) })
方法2:兼容写法(适配低版本环境)
用普通循环搭配Object.keys遍历对象属性,手动收集符合条件的data值:
const targetArr = [] this.originalArrayData.forEach(item => { Object.keys(item).forEach(key => { const subItem = item[key] if (subItem && typeof subItem === 'object' && arrayOfIds.includes(subItem.grid_col_id)) { targetArr.push(subItem.data) } }) })
- 普通对象不能直接调用数组遍历方法,需要先用
Object.keys/Object.values/Object.entries拿到可遍历的属性集合 - 增加类型判断是为了跳过
header(字符串类型)、id(数字类型)这类非格子属性,避免读取grid_col_id时报错 - 用示例数据测试,两种方法输出结果均为
["10", "14"],如果需要数字类型结果,可以在提取时做类型转换:Number(matchedItem.data)
内容的提问来源于stack exchange,提问作者Beginner_Hello

