根据嵌套数组重新组合对象数组

Regroup array of objects based on nested array

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

输入

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] }))],
  []
);

创建一个索引爱好的对象。当遍历人时,创建一个带有 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);

您可以减少数组并为结果集查找同名项。

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; }

简单的 Array.prototype.reduce() teamed up with Array.prototype.forEach() to loop over the list of hobbies, together with 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%;}

使用 Array#reduce。您可以像这样 {hobbies,...b}

使用 Spread operator 在每次迭代中传递对象

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))