1

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

输入

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

4 回答 4

2

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

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

于 2020-03-12T08:26:00.500 回答
2

SimpleArray.prototype.reduce()联手Array.prototype.forEach()循环遍历列表hobbies,再加上解构赋值语法可以轻松解决问题:

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

于 2020-03-12T08:29:51.920 回答
1

而是创建一个索引该爱好的对象。迭代人员时,如果它尚不存在,则使用 aname和数组创建一个新对象,然后推送到数组:person_detailsperson_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可以说不是用于此类事情的正确工具,但如果您想使用它:

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

于 2020-03-12T08:22:38.843 回答
0

使用Array#reduce.you 可以像这样使用Spread 运算符在每次迭代中传递对象{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))

于 2020-03-12T08:32:50.827 回答