【问题标题】:Regroup array of objects based on nested array基于嵌套数组重新组合对象数组
【发布时间】:2020-03-12 08:18:13
【问题描述】:

我有一个对象数组。每个对象包含另一个内部数组。我想将每个内部数组作为外部对象,并将剩余的旧外部元素作为新创建的外部对象的子属性。

输入

data = [
    {
      name: "Sam",
      ssn: 123,
      age: 25,
      hobbies: [{ name: "cricket" }, { name: "football" }]
    },
    {
      name: "John",
      ssn: 234,
      age: 25,
      hobbies: [{ name: "cricket" }, { name: "football" }]
    },
    {
      name: "Mathew",
      ssn: 345,
      age: 25,
      hobbies: [{ name: "cricket" }, { name: "football" }, {name: "carroms"}]
    }
  ];

预期输出

[
      {
        name: "cricket",
        person_details: [
          { name: "Sam", ssn: 123, age: 25 },
          { name: "John", ssn: 234, age: 25 },
          { name: "Mathew", ssn: 345, age: 25 }
        ]
      },
      {
        name: "football",
        person_details: [
          { name: "Sam", ssn: 123, age: 25 },
          { name: "John", ssn: 234, age: 25 },
          { name: "Mathew", ssn: 345, age: 25 }
        ]
      },
      {
        name: "carroms",
        person_details: [          
          { name: "Mathew", ssn: 345, age: 25 }
        ]
      }
    ]

我使用 Reduce 的尝试如下

this.data = this.data.reduce(
  (a, x) => [...x.hobbies.map(h => ({ ...x, hobbies: [h] }))],
  []
);

【问题讨论】:

  • 为什么要在输出中输入hobbies:?你为什么不在循环中访问h.name
  • 当我看到这样的代码时,我想知道你是不是在尝试,或者你只是随机地将一些东西放在一起,所以我们不会因为没有显示尝试而关闭问题。
  • 嘿伙计。我尝试了一些东西,但我不清楚如何通过添加扩展、箭头、es6 功能来简单地实现这一点。这可以很容易地使用多个 for 循环来完成,但我的目的是尽量减少复杂性和代码。
  • 使用 spread 和 reduce 来缩短代码并不总能最小化复杂性。写清楚。

标签: javascript arrays reduce arrayofarrays


【解决方案1】:

您可以减少数组并为结果集寻找相同名称的项目。

var data = [{ name: "Sam", ssn: 123, age: 25, hobbies: [{ name: "cricket" }, { name: "football" }] }, { name: "John", ssn: 234, age: 25, hobbies: [{ name: "cricket" }, { name: "football" }] }, { name: "Mathew", ssn: 345, age: 25, hobbies: [{ name: "cricket" }, { name: "football" }, { name: "carroms" }] }],
    result = data.reduce((r, { hobbies, ...o }) => {
        hobbies.forEach(({ name }) => {
            var group = r.find(q => q.name === name);
            if (!group) r.push(group = { name, person_details: [] });
            group.person_details.push(o);
        })
        return r;
    }, []);

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

【讨论】:

【解决方案2】:

简单的Array.prototype.reduce()Array.prototype.forEach() 联手循环hobbies 的列表,再加上destructuring assignment 语法可以轻松解决问题:

const data = [{name:"Sam",ssn:123,age:25,hobbies:[{name:"cricket"},{name:"football"}]},{name:"John",ssn:234,age:25,hobbies:[{name:"cricket"},{name:"football"}]},{name:"Mathew",ssn:345,age:25,hobbies:[{name:"cricket"},{name:"football"},{name:"carroms"}]}],
  
      result = data.reduce((r,{hobbies, ...userData}) => (
        hobbies.forEach(({name}) => (
          match = r.find(({hobby}) => hobby == name),
          match ?
          match['person_details'].push({...userData}) :
          r.push({hobby:name, person_details: [{...userData}]})
        ))
     , r), [])

console.log(result)
.as-console-wrapper{min-height:100%;}

【讨论】:

  • 输出应该是一个数组,而不是一个对象
【解决方案3】:

改为创建一个索引该爱好的对象。迭代人员时,如果尚不存在,则使用 nameperson_details 数组创建一个新对象,然后推送到 person_details 数组:

const data = [
  {
    name: "Sam",
    ssn: 123,
    age: 25,
    hobbies: [{ name: "cricket" }, { name: "football" }]
  },
  {
    name: "John",
    ssn: 234,
    age: 25,
    hobbies: [{ name: "cricket" }, { name: "football" }]
  },
  {
    name: "Mathew",
    ssn: 345,
    age: 25,
    hobbies: [{ name: "cricket" }, { name: "football" }, {name: "carroms"}]
  }
];
const peopleByHobbies = {};
for (const { hobbies, ...personData } of data) {
  for (const { name } of hobbies) {
    if (!peopleByHobbies[name]) peopleByHobbies[name] = { name, person_details: [] };
    peopleByHobbies[name].person_details.push({ ...personData });
  }
}
const output = Object.values(peopleByHobbies);
console.log(output);

reduce 可以说是 not the right tool to use 用于这种事情,但如果你想使用它:

const data = [
  {
    name: "Sam",
    ssn: 123,
    age: 25,
    hobbies: [{ name: "cricket" }, { name: "football" }]
  },
  {
    name: "John",
    ssn: 234,
    age: 25,
    hobbies: [{ name: "cricket" }, { name: "football" }]
  },
  {
    name: "Mathew",
    ssn: 345,
    age: 25,
    hobbies: [{ name: "cricket" }, { name: "football" }, {name: "carroms"}]
  }
];
const peopleByHobbies = data.reduce((peopleByHobbies, { hobbies, ...personData }) => {
  for (const { name } of hobbies) {
    if (!peopleByHobbies[name]) peopleByHobbies[name] = { name, person_details: [] };
    peopleByHobbies[name].person_details.push({ ...personData });
  }
  return peopleByHobbies;
}, {});
const output = Object.values(peopleByHobbies);
console.log(output);

【讨论】:

    【解决方案4】:

    使用Array#reduce 。您可以使用Spread operator 像这样{hobbies,...b} 在每次迭代中传递对象

    const arr = [{ name: "Sam", ssn: 123, age: 25, hobbies: [{ name: "cricket" }, { name: "football" }] }, { name: "John", ssn: 234, age: 25, hobbies: [{ name: "cricket" }, { name: "football" }] }, { name: "Mathew", ssn: 345, age: 25, hobbies: [{ name: "cricket" }, { name: "football" }, { name: "carroms" }] } ];
    
    const res = arr.reduce((acc, {hobbies,...b}) => {
                hobbies.forEach(i => {
                  acc[i.name] = acc[i.name] || {
                    name: i.name,
                    persional_details: []
                  };
                acc[i.name].persional_details.push(b)
            })
            return acc
          }, {});
    
    console.log(Object.values(res))

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-04-15
      • 2016-11-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多