Как сгруппировать и отсортировать массив объектов? - PullRequest
0 голосов
/ 11 июля 2019

У меня есть массив объектов, который я должен сгруппировать и отсортировать:

[
  {
    id: 123,
    group: 'abc',
    metadata: {
      name: 'tom'
    },
    date: ISODate("2019-07-08T20:33:40.475Z")
  },
  {
    id: 456,
    group: 'def',
    metadata: {
      name: 'bob'
    },
    date: ISODate("2019-07-08T20:33:40.475Z")
  },
  {
    id: 789,
    group: 'def',
    metadata: {
      name: 'bob'
    },
    date: ISODate("2019-07-10T20:33:40.475Z")
  },
  {
    id: 234,
    group: 'ghi',
    metadata: {
      name: 'frank'
    },
    date: ISODate("2019-07-10T20:33:40.475Z")
  },
  {
    id: 567,
    group: 'abc',
    metadata: {
      name: 'tom'
    },
    date: ISODate("2019-07-10T20:33:40.475Z")
  }
]

Сначала мне нужно сгруппировать элементы по значению группы, затем мне нужно отсортировать элементы этого сгруппированного массивапо дате.

Для группировки я пробовал это:

const result = array.reduce(function (r, a) {
    r[a.group] = r[a.group] || [];
    r[a.group].push(a);
    return r;
}, Object.create(null));

Но результат не такой, как ожидалось, и элементы не отсортированы по дате.

Результатможет / должен выглядеть примерно так:

[
  [
    {
      id: 123,
      group: 'abc',
      metadata: {
        name: 'tom'
      },
      date: ISODate("2019-07-08T20:33:40.475Z")
    },
    {
      id: 567,
      group: 'abc',
      metadata: {
        name: 'tom'
      },
      date: ISODate("2019-07-10T20:33:40.475Z")
    }
  ],
  [
    {
      id: 456,
      group: 'def',
      metadata: {
        name: 'bob'
      },
      date: ISODate("2019-07-08T20:33:40.475Z")
    },
    {
      id: 789,
      group: 'def',
      metadata: {
        name: 'bob'
      },
      date: ISODate("2019-07-10T20:33:40.475Z")
    }
  ],
  [
    {
      id: 234,
      group: 'ghi',
      metadata: {
        name: 'frank'
      },
      date: ISODate("2019-07-10T20:33:40.475Z")
    }
  ]
]

Ответы [ 2 ]

0 голосов
/ 11 июля 2019

Я бы предложил использовать Лодаш .

var ISODate = function(str) { return str };

var data = [
  {
    id: 123,
    group: 'abc',
    metadata: {
      name: 'tom'
    },
    date: ISODate("2019-07-08T20:33:40.475Z")
  },
  {
    id: 456,
    group: 'def',
    metadata: {
      name: 'bob'
    },
    date: ISODate("2019-07-08T20:33:40.475Z")
  },
  {
    id: 789,
    group: 'def',
    metadata: {
      name: 'bob'
    },
    date: ISODate("2019-07-10T20:33:40.475Z")
  },
  {
    id: 234,
    group: 'ghi',
    metadata: {
      name: 'frank'
    },
    date: ISODate("2019-07-10T20:33:40.475Z")
  },
  {
    id: 567,
    group: 'abc',
    metadata: {
      name: 'tom'
    },
    date: ISODate("2019-07-10T20:33:40.475Z")
  }
]

console.log(
  _.mapValues(
    _.groupBy(data, 'group'),
    function(item) { return _.orderBy(item, ['date'], ['asc']) }
  )
)

https://codepen.io/anon/pen/bPzmOr

0 голосов
/ 11 июля 2019

Используйте reduce для группировки значений и sort для их сортировки, используя map также из-за структуры вложенного массива.

const arr = [{id:123,group:'abc',metadata:{name:'tom'},date:"2019-07-08T20:33:40.475Z"},{id:456,group:'def',metadata:{name:'bob'},date:"2019-07-08T20:33:40.475Z"},{id:789,group:'def',metadata:{name:'bob'},date:"2019-07-10T20:33:40.475Z"},{id:234,group:'ghi',metadata:{name:'frank'},date:"2019-07-10T20:33:40.475Z"},{id:567,group:'abc',metadata:{name:'tom'},date:"2019-07-10T20:33:40.475Z"}];
const res = Object.values(arr.reduce((a, { group, ...r }) => {
  (a[group] = a[group] || []).push({ group, ...r });
  return a;
}, {})).map(e => e.sort(({ date: a }, { date: b }) => new Date(a) - new Date(b)));

console.log(res);
.as-console-wrapper { max-height: 100% !important; top: auto; }

(Я убрал функцию ISODate и просто сохранил строковую дату, чтобы сделать исполняемый фрагмент.)

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