Перегруппировать массив объектов на основе вложенного массива - PullRequest
1 голос
/ 12 марта 2020

У меня есть массив объектов. Каждый объект содержит еще один внутренний массив. Я хотел бы взять каждый внутренний массив в качестве внешнего объекта и поместить оставшиеся старые внешние элементы в качестве вспомогательных свойств вновь созданного внешнего объекта.

Ввод

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

То, что я пытался использовать при уменьшении следующим образом

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

Ответы [ 4 ]

2 голосов
/ 12 марта 2020

Вы можете уменьшить массив и искать элементы с тем же именем для набора результатов.

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 голосов
/ 12 марта 2020

Простой Array.prototype.reduce() объединился с Array.prototype.forEach() до l oop в списке 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%;}
1 голос
/ 12 марта 2020

Создайте объект, индексированный вместо хобби. При переборе по людям создайте новый объект с массивом name и person_details, если он еще не существует, а затем добавьте pu sh в массив 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 возможно не тот инструмент, который можно использовать для такого рода вещей, но если вы хотите его использовать:

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);
0 голосов
/ 12 марта 2020

Используя Array#reduce. Вы можете передать объект на каждой итерации, используя Оператор спреда , как это {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))
...