Как использовать сокращение для возврата сопоставленного объекта с массивами в качестве значений? - PullRequest
0 голосов
/ 26 мая 2020

У меня есть массив отдельных объектов. У некоторых такое же значение date. Я хотел бы сгруппировать их с одним и тем же date вместе и вернуть сопоставленный объект, где каждый date является ключом, а его значение - массивом объекта (ов) с той же датой. Вот массив:

const arr = [
  {
    date: '2/2/20',
    name: 'joe',
    age: 22
  },
  {
    date: '3/3/20',
    name: 'john',
    age: 67
  },
  {
    date: '2/2/20',
    name: 'chuck',
    age: 34
  },
  {
    date: '3/3/20',
    name: 'bob',
    age: 28
  },
  {
    date: '4/4/20',
    name: 'bill',
    age: 51
  }
]

Я знаю, что что-то подобное можно сделать с помощью map().filter(), но это не то, что я ищу, и, кроме того, я пытаюсь сделать это с помощью reduce(), чтобы экономия ресурсов.

Пока у меня есть:

arr.reduce((acc, person) => {
  acc[person.date] = [ person ];
  return acc;
}, {});

Это возвращает только последнее совпадение, а не все совпадения:

{
  '2/2/20': [ { date: '2/2/20', name: 'chuck', age: 34 } ],
  '3/3/20': [ { date: '3/3/20', name: 'bob', age: 28 } ],
  '4/4/20': [ { date: '4/4/20', name: 'bill', age: 51 } ]
}

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

arr.reduce((acc, person) => {
  acc[person.date] = acc[person.date] + 1 || 1
  return acc
}, {})

Это возвращает:

{ '2/2/20': 2, '3/3/20': 2, '4/4/20': 1 }

Итак, как можно Я использую reduce(), чтобы получить объект, содержащий все совпадения?

Ответы [ 2 ]

2 голосов
/ 26 мая 2020

Инициализируется пустым массивом, если acc[person.date] не существует, и push независимо:

arr.reduce((acc, person) => {
    acc[person.date] = (acc[person.date] || []);
    acc[person.date].push(person);
    return acc;
}, {});

Подход с однострочным деструктурированием / расширением:

arr.reduce((acc, { date, ...o }) => ({ ...acc, [date]: [...(acc[date] || []), { date, ...o }), {});
1 голос
/ 26 мая 2020

Ответ Джека Бэшфорда, кажется, именно то, что вы ищете. Я бы просто добавил, что это очень распространенная операция, которую часто называют groupBy. Это реализовано в большинстве функциональных вспомогательных библиотек (например, Loda sh). Вы также можете реализовать это самостоятельно, например:

const groupBy = (cb, arr) =>
  arr.reduce((grouped, el) => {
    const key = cb(el)
    return {
      ...grouped,
      [key]: [...grouped[key] || [], el]
    }
  }, {})

(Обратите внимание, что приведенная выше реализация является всего лишь примером и не должна считаться эффективной реализацией. См. Loda sh groupBy implementation .

, а затем для вашего варианта использования:

groupBy(el => el.date, arr)

, что полезно, если вы планируете выполнять аналогичные операции.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...