Попытка сгруппировать массив объектов под одинаковыми ключами, что приводит к созданию нового массива объектов. - PullRequest
0 голосов
/ 16 февраля 2020

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

let messages = [
  {text: "A", status: 'r', created_at: "2020-02-06"},
  {text: "B", status: 's', created_at: "2020-02-06"},
  {text: "C", status: 'r', created_at: "2020-02-06"},
  {text: "D", status: 's', created_at: "2020-02-07"},
  {text: "E", status: 's', created_at: "2020-02-07"},
  {text: "F", status: 'r', created_at: "2020-02-09"},
  {text: "G", status: 's', created_at: "2020-02-09"},
  {text: "H", status: 's', created_at: "2020-02-10"}
]

Я использую vuejs для рендеринга этих сообщений в приложении чата (аналогично WhatsApp), где я хочу отображать дату сверху и сообщения под эта дата в хронологическом порядке, так же, как WhatsApp. Я получаю сообщения от API в хронологическом порядке, например, массив messages, который я вставил выше. Я хотел бы получить следующий вывод, чтобы я мог использовать v-for directive в vuejs до l oop через messages и отображать их в соответствии с датой их создания:

  output:
    [
      {
        dt: "2020-02-06",
        arr: [
            {text: "A", status: 'r', created_at: "2020-02-06"},
            {text: "B", status: 's', created_at: "2020-02-06"},
            {text: "C", status: 'r', created_at: "2020-02-06"},
        ]
      },
      {
        dt: "2020-02-07",
        arr: [
            {text: "D", status: 's', created_at: "2020-02-06"},
            {text: "E", status: 's', created_at: "2020-02-06"},
        ]
      },
      {
        dt: "2020-02-09",
        arr: [
            {text: "F", status: 'r', created_at: "2020-02-09"},
            {text: "G", status: 's', created_at: "2020-02-09"},
        ]
      },
        {
        dt: "2020-02-10",
        arr: [
           {text: "H", status: 's', created_at: "2020-02-10"}
        ]
      },
    ]

Есть ли в loda библиотека sh, которая может достичь этого напрямую?

Что я пробовал до сих пор:

Я смог сгруппировать даты в массив без повторения дат, вот так:

let dates = messages.map((item => {
    return item.created_at
}))
let uniq = [...new Set(dates)];
console.log(uniq)

... что дает следующий вывод:

uniq = ["2020-02-06", "2020-02-07", "2020-02-09", "2020-02-10"]

Я не могу двигаться вперед.

Заранее спасибо!

Ответы [ 4 ]

2 голосов
/ 16 февраля 2020

Используйте loda sh для группировки по created_at, а затем сопоставьте с требуемым форматом:

const messages = [
  {text: "A", status: 'r', created_at: "2020-02-06"},
  {text: "B", status: 's', created_at: "2020-02-06"},
  {text: "C", status: 'r', created_at: "2020-02-06"},
  {text: "D", status: 's', created_at: "2020-02-07"},
  {text: "E", status: 's', created_at: "2020-02-07"},
  {text: "F", status: 'r', created_at: "2020-02-09"},
  {text: "G", status: 's', created_at: "2020-02-09"},
  {text: "H", status: 's', created_at: "2020-02-10"}
]

const result = _.map(
  _.groupBy(messages, 'created_at'),
  (arr, dt) => ({ dt, arr })
)

console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.js"></script>
1 голос
/ 16 февраля 2020

Использование reduce для создания объекта и получение Object.values упростят.

const update = data => {
  return Object.values(
    data.reduce((acc, curr) => {
      const dt = curr.created_at;
      acc[dt] =
        dt in acc
          ? { dt, arr: [...acc[dt].arr, { ...curr }] }
          : { dt, arr: [{ ...curr }] };
      return acc;
    }, {})
  );
};

let messages = [
  { text: "A", status: "r", created_at: "2020-02-06" },
  { text: "B", status: "s", created_at: "2020-02-06" },
  { text: "C", status: "r", created_at: "2020-02-06" },
  { text: "D", status: "s", created_at: "2020-02-07" },
  { text: "E", status: "s", created_at: "2020-02-07" },
  { text: "F", status: "r", created_at: "2020-02-09" },
  { text: "G", status: "s", created_at: "2020-02-09" },
  { text: "H", status: "s", created_at: "2020-02-10" }
];

console.log(update(messages));
1 голос
/ 16 февраля 2020

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

let messages = [
  {text: "A", status: 'r', created_at: "2020-02-06"},
  {text: "B", status: 's', created_at: "2020-02-06"},
  {text: "C", status: 'r', created_at: "2020-02-06"},
  {text: "D", status: 's', created_at: "2020-02-07"},
  {text: "E", status: 's', created_at: "2020-02-07"},
  {text: "F", status: 'r', created_at: "2020-02-09"},
  {text: "G", status: 's', created_at: "2020-02-09"},
  {text: "H", status: 's', created_at: "2020-02-10"}
];
const messagesByDate = {};
for (const message of messages) {
  if (!messagesByDate[message.created_at]) {
    messagesByDate[message.created_at] = [];
  }
  messagesByDate[message.created_at].push(message);
}
const output = Object.entries(messagesByDate).map(([dt, arr]) => ({ dt, arr }));
console.log(output);
0 голосов
/ 16 февраля 2020

Я нашел решение без использования какой-либо внешней библиотеки:

const messages = [
  {text: "A", status: 'r', created_at: "2020-02-06"},
  {text: "B", status: 's', created_at: "2020-02-06"},
  {text: "C", status: 'r', created_at: "2020-02-06"},
  {text: "D", status: 's', created_at: "2020-02-07"},
  {text: "E", status: 's', created_at: "2020-02-07"},
  {text: "F", status: 'r', created_at: "2020-02-09"},
  {text: "G", status: 's', created_at: "2020-02-09"},
  {text: "H", status: 's', created_at: "2020-02-10"}
]

let dupDates = messages.map((item => {
	return item.created_at
}))
let uniq = [...new Set(dupDates)];
let grouping = uniq.map(uniqItem => {
	let ret = messages.filter(msg => {
  	return msg.created_at === uniqItem
  })
  return {
  	 dt: uniqItem,
         arr: ret
  }
})
console.log(grouping)
 
...