按嵌套数组对数组进行分组

Grouping Arrays By Nested Arrays

我有以下数组,我想将其转换为具有唯一 hobbies 作为键的对象

const arr = [
  { name: 'Joe', hobbies: ['skating', 'biking', 'music'] },
  { name: 'Kim', hobbies: ['fishing', 'biking', 'karate'] },
  { name: 'Ben', hobbies: ['surfing'] },
]

我使用 lodash 的便利 groupBy 函数,但它将多个数组元素分组为单个键,就像这样

{
  'skating,biking,music': [
    { name: 'Joe' }
  ],
  'fishing,biking,karate': [
    { name: 'Kim' }
  ],
  'surfing': [
    { name: 'Ben' }
  ],
}

我需要的是下面的输出(注意每个对象都是重复的各自的爱好)

{
  biking: [
    { name: 'Joe' },
    { name: 'Kim' }
  ],
  skating: [
    { name: 'Joe' }
  ],
  karate: [
    { name: 'Kim' }
  ],
  surfing: [
    { name: 'Ben' }
  ],
  ...
}

有没有一种简单的方法可以对这个数组进行分组,而无需循环遍历每个数组元素,将它们拆分并重新分组?如果有我不知道的更好的实用方法,我想避免这种情况

您可以迭代每个项目和每个爱好,然后将其添加到 result 对象:

const arr = [
  { name: 'Joe', hobbies: ['skating', 'biking', 'music'] },
  { name: 'Kim', hobbies: ['fishing', 'biking', 'karate'] },
  { name: 'Ben', hobbies: ['surfing'] }
]

const result = {};
arr.forEach(item => 
  item.hobbies.forEach(hobbie => 
    result[hobbie] = (result[hobbie] || []).concat({name: item.name})
  )
)

console.log(result);

const arr = [
  { name: 'Joe', hobbies: ['skating', 'biking', 'music'] },
  { name: 'Kim', hobbies: ['fishing', 'biking', 'karate'] },
  { name: 'Ben', hobbies: ['surfing'] }
]

const result = {};
arr.forEach(item => 
  item.hobbies.forEach(hobbie => 
    result[hobbie] = result[hobbie]?[...result[hobbie],{name: item.name}]: [{name: item.name}]
  )
)

console.log(result);

为了更好地理解,我已将 arr 重命名为 people

const people = [
  { name: 'Joe', hobbies: ['skating', 'biking', 'music'] },
  { name: 'Kim', hobbies: ['fishing', 'biking', 'karate'] },
  { name: 'Ben', hobbies: ['surfing'] },
];

function transform(people) {
  // get all hobbies and remove duplicates
  const hobbies = [... new Set(
    people.reduce((hobbies, person) => hobbies.concat(person.hobbies),  [])
  )];
  const res = {};
  // take a hobby and use it as key
  for (let hobby of hobbies) {
    res[hobby] = people
      .filter((person) => person.hobbies.includes(hobby))
      .map((person) => { return { name: person.name }; });
  }
  return res;
}

console.log(transform(people));