Я пытаюсь сгруппировать объекты с одинаковым свойством. Я начинаю с массива объектов и хочу закончить массивом, который содержит несколько массивов, каждый из которых содержит объекты, которые имеют одно и то же свойство.

Скажем, у меня есть этот массив объектов фильма, у каждого из них есть свойство year, и я хочу сгруппировать все фильмы с таким же свойством year в их собственный массив и, наконец, иметь все эти массивы в одном массиве.

// This is the array I've got
const films = [
  {
    name='film 1',
    year='1992'
  },
  {
    name='film 2',
    year='1992'
  },
  {
    name='film 3',
    year='1995'
  },
  {
    name='film 4',
    year='1995'
  },
  {
    name='film 5',
    year='1995'
  },
  {
    name='film 6',
    year='1998'
  },
  {
    name='film 7',
    year='1998'
  },
]

// And this is the array I want to end up with
const filmsSorted = [
  [
    {
      name='film 1',
      year='1992'
    },
    {
      name='film 2',
      year='1992'
    },
  ]
  [
    {
      name='film 3',
      year='1995'
    },
    {
      name='film 4',
      year='1995'
    },
    {
      name='film 5',
      year='1995'
    },
  ]
  [
    {
      name='film 6',
      year='1998'
    },
    {
      name='film 7',
      year='1998'
    },
  ]
]

Имейте в виду, что у меня нет свойства year заранее, и я должен динамически работать с любым годом, который я получаю в исходном массиве.

Хотя здесь много вопросов о сортировке и фильтрации массивов, я не смог найти ответ на эту конкретную проблему. Я пытался использовать reduce() и filter() и их комбинацию, но я просто не могу понять, как это сделать. Я нашел несколько возможных решений (преобразование его в объект и обратно в массив), но мне бы очень хотелось увидеть несколько разных способов решения этой проблемы, чтобы помочь мне лучше рассуждать об этом.

0
Syknapse 27 Окт 2019 в 13:34

3 ответа

Лучший ответ

Просто возьмите хеш-таблицу и сгруппируйте ее по year и возьмите значения из хеш-таблицы.

Бонус: отсортированный результат, потому что ключи объекта отсортированы, если ключи можно прочитать как индексы массива.

var films = [{ name: 'film 1', year: '1992' }, { name: 'film 2', year: '1992' }, { name: 'film 3', year: '1995' }, { name: 'film 4', year: '1995' }, { name: 'film 5', year: '1995' }, { name: 'film 6', year: '1998' }, { name: 'film 7', year: '1998' }],
    grouped = Object.values(
        films.reduce((r, o) => {
            (r[o.year] = r[o.year] || []).push(o);
            return r;
        }, {})
    );

console.log(grouped);
.as-console-wrapper { max-height: 100% !important; top: 0; }
2
Nina Scholz 27 Окт 2019 в 10:49

Я нашел другой способ сделать это, я оставлю это здесь на случай, если это будет полезно для будущих читателей.

const films = [{ name: 'film 1', year: '1992' }, { name: 'film 2', year: '1992' }, { name: 'film 3', year: '1995' }, { name: 'film 4', year: '1995' }, { name: 'film 5', year: '1995' }, { name: 'film 6', year: '1998' }, { name: 'film 7', year: '1998' }]
let filmsSorted = []
let years = {}

films.forEach(film => {
    if (!years[film.year]) years[film.year] = []
    years[film.year].push(film)
})

filmsSorted = Object.values(years)

Это создает промежуточный объект, который имеет пары ключ / значение общих свойств (лет) и массивы всех объектов, содержащих это свойство. Затем мы можем просто создать массив значений и в итоге получим требуемую сортировку.

0
Syknapse 4 Ноя 2019 в 10:16

Попробуй это:

const films = [
  {
    name: 'film 1',
    year: '1992'
  },
  {
    name: 'film 2',
    year: '1992'
  },
  {
    name: 'film 3',
    year: '1995'
  },
  {
    name: 'film 4',
    year: '1995'
  },
  {
    name: 'film 5',
    year: '1995'
  },
  {
    name: 'film 6',
    year: '1998'
  },
  {
    name: 'film 7',
    year: '1998'
  }
]

const result = films.reduce((acc, curr) => {
  if (acc.some(e => e[0].year === curr.year)) acc.filter(e => e[0].year === curr.year)[0].push(curr)
  else acc.push([curr])
  
  return acc
}, [])

console.log(result)
1
cherryblossom 27 Окт 2019 в 10:52
58578573