如何高效地将嵌套对象数组扁平化为键值映射数组

11次阅读

如何高效地将嵌套对象数组扁平化为键值映射数组

本文介绍一种使用 map对象遍历结合的方式,将含 items 数组(每个 item 是 { [key]: String, quantity: number } 结构)的原始对象数组,转换为每个对象直接以产品名为属性、数量为值的新数组。

在实际开发中,我们常遇到数据结构嵌套较深的场景:例如订单列表中每个订单包含多个商品项(items),而每项又以动态字段名(如 productOne、productTwo)标识商品类型,quantity 表示数量。此时若需将 items “展开”为同级属性(如 crust: 2.2, dust: 34),就需要一次语义清晰、可维护性强的扁平化处理。

核心思路是:对原数组每一项执行 map,创建新对象副本 → 遍历其 items 数组 → 对每个 item 动态提取非 quantity 字段作为属性名,quantity 值作为对应属性值 → 最后删除 items 字段,返回精简后的对象。

以下是推荐实现(已优化可读性与健壮性):

function flattenItems(arr) {   return arr.map(item => {     // 浅拷贝原对象,避免污染源数据     const flattened = { ...item };      // 遍历 items 数组     for (const entry of item.items || []) {       // 遍历 entry 的每个键,识别 product 字段和 quantity       let productName = null;       let quantityValue = null;        for (const key in entry) {         if (key === 'quantity') {           quantityValue = entry[key];         } else if (typeof entry[key] === 'string') {           productName = entry[key];         }       }        // 安全赋值:仅当两者均存在时才挂载到结果对象       if (productName !== null && quantityValue !== undefined) {         flattened[productName] = quantityValue;       }     }      // 移除原始 items 字段     delete flattened.items;      return flattened;   }); }  // 示例输入 const firstArray = [   {     amount: 343,     code: "RCU8YI0NKS",     items: [       { productOne: "crust", quantity: 2.2 },       { productTwo: "dust", quantity: 34 }     ],     user_id: "wewewefwOHG22323kj"   },   {     amount: 343,     code: "RCU8YI0NKS",     items: [       { productTwo: "dust", quantity: 32 },       { productThree: "must", quantity: 34 }     ],     user_id: "m2LgLRD9MEVNAX56JTpRYDkOOjd2"   } ];  console.log(flattenItems(firstArray)); // 输出即为目标格式 secondArray

注意事项

  • 该方法时间复杂度为 O(n × m)(n 为外层数组长度,m 为单个 items 平均长度),属最优解——因必须访问每个 item 才能提取键值,无可避免;
  • 使用 …item 浅拷贝更符合现代 js 实践,比 Object.assign({}, item) 更简洁;
  • 显式检查 item.items || [] 和 typeof entry[key] === ‘string’ 可防御空值或异常结构;
  • 若存在多个 product 字段(如同时有 productOne 和 productTwo),当前逻辑取第一个非 quantity 字符串作为 product name —— 若业务要求更精确匹配(如只认 product.* 开头的 key),可替换为正则校验:/^(product|item)/i.test(key);
  • 若需支持重复 product 名合并(如多个 dust 合并为总量),可在赋值前做累加判断。

此方案简洁、可读、可扩展,适用于中后台数据聚合、报表生成及 API 响应适配等典型场景。

text=ZqhQzanResources