You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何基于子属性筛选父对象并按Forms组织JavaScript数据?

针对你的JavaScript数据重组问题的解答

首先,关于你提到的“依靠子属性决定父对象组织方式”的场景,这个在数据处理领域有专门的术语:

  • 最通用的称呼是数据重塑(Data Reshaping),指将数据从一种结构转换为另一种结构以匹配展示或处理需求的操作。
  • 如果更聚焦于“按子属性值对父对象进行归类分组”的具体操作,也可以称为基于子属性的分组(Grouping by Child Attribute),在前端开发中有时候也会被叫做结构化数据重组。

接下来,针对你需要按forms整理数据、克隆原数据不修改的需求,我分别提供原生JavaScript和Lodash的实现方案:

原生JavaScript实现

假设你的原数据结构类似这样(如果结构不同可以调整逻辑):

const originalData = [
  { id: 1, name: "Item A", forms: ["form1", "form2"] },
  { id: 2, name: "Item B", forms: ["form2"] },
  { id: 3, name: "Item C", forms: ["form1", "form3"] }
];

我们可以通过遍历+深度克隆的方式构建关联结构:

function reshapeDataByForms(original) {
  const result = {};
  
  original.forEach(item => {
    // 使用structuredClone深度克隆,避免修改原数据(现代浏览器/Node.js 17+支持)
    const clonedItem = structuredClone(item);
    
    clonedItem.forms.forEach(form => {
      // 初始化对应form的数组(如果不存在)
      if (!result[form]) {
        result[form] = [];
      }
      // 将克隆后的对象加入对应分组
      result[form].push(clonedItem);
    });
  });
  
  return result;
}

// 调用示例
const reshapedData = reshapeDataByForms(originalData);

克隆方式说明

  • structuredClone:支持大多数数据类型(日期、正则、Map/Set等),是原生中最可靠的深度克隆方式,但注意旧浏览器不支持。
  • 如果需要兼容旧环境,可以用JSON.parse(JSON.stringify(item)),但这种方式无法处理函数、Symbol、循环引用等特殊类型。

Lodash实现

Lodash提供了更简洁的工具函数来处理克隆和分组,代码会更简洁:

const _ = require('lodash');

function reshapeDataByFormsLodash(original) {
  const result = {};
  
  _.forEach(original, item => {
    // 使用cloneDeep深度克隆原对象
    const clonedItem = _.cloneDeep(item);
    
    _.forEach(clonedItem.forms, form => {
      // 确保对应form的数组存在,然后添加克隆对象
      result[form] = _.get(result, form, []).concat(clonedItem);
    });
  });
  
  return result;
}

// 调用示例
const reshapedData = reshapeDataByFormsLodash(originalData);

或者用更函数式的写法:

const reshapeDataByFormsLodash = _.flow(
  _.flatMap(item => 
    _.cloneDeep(item).forms.map(form => ({ ...item, formKey: form }))
  ),
  grouped => _.groupBy(grouped, 'formKey'),
  grouped => _.mapValues(grouped, items => _.map(items, _.omit('formKey')))
);

注意事项

  • 如果你的forms属性是单个字符串(不是数组),可以在遍历前先转成数组:const forms = Array.isArray(item.forms) ? item.forms : [item.forms]。
  • 所有实现都保证了原数据不会被修改,因为我们对每个父对象都做了深度克隆。

内容的提问来源于stack exchange,提问作者Acts7Seven

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 10:09:02