JS — группировка массива объектов с одинаковым значением свойства, но другим именем

#javascript

#javascript

Вопрос:

У меня есть этот массив message объектов, и я хотел сгруппировать их с одинаковым from - to значением или наоборот.

 const msgs = [
  { id: '1', from: 'mimi', to: 'gudo', createdAt: '2021-01-01:T-50-249' }, //GROUP THIS
  { id: '5', from: 'gudo', to: 'mimi', createdAt: '2021-01-01:T-46-462' }, //

  { id: '2', from: 'john', to: 'gudo', createdAt: '2021-01-01:T-50-249' }, //GROUP THIS
  { id: '3', from: 'gudo', to: 'john', createdAt: '2021-01-01:T-46-462' }, //

  { id: '7', from: 'dave', to: 'gudo', createdAt: '2021-01-05' }, //GROUP THIS
]
 

Это мой подход к этому, но все еще есть проблема, я понятия не имею, как добавить объект, у которого нет пары, которая является объектом, имеющим from значение свойства dave

 let msg = [
  { id: '2', from: 'mimi', to: 'gudo', createdAt: '2021-01-01'},
  { id: '3', from: 'gudo', to: 'mimi', createdAt: '2021-01-02' },
  { id: '5', from: 'gudo', to: 'john', createdAt: '2021-01-03' },
  { id: '4', from: 'john', to: 'gudo', createdAt: '2021-01-05' },
  { id: '7', from: 'dave', to: 'gudo', createdAt: '2021-01-05' },
]

const sent = msg.filter(i => i.from === 'gudo');
const received = msg.filter(i => i.to === 'gudo');

const res = [];

for (let i = 0; i < sent.length; i  ) {
   const curMine = sent[i];
   const pair = [];

   for (let j = 0; j < received.length; j  ) {
      const curFrom = received[j];
      
      if(curMine.to === curFrom.from) {
        pair.push(curMine);
        pair.push(curFrom);
      } 
   }
   
   res.push(pair);
}

console.log(res) 

Ожидаемый результат:

 [
  [
    { id: '2', from: 'mimi', to: 'gudo', createdAt: '2021-01-01'},
    { id: '3', from: 'gudo', to: 'mimi', createdAt: '2021-01-02' },
  ],
  [
    { id: '5', from: 'gudo', to: 'john', createdAt: '2021-01-03' },
    { id: '4', from: 'john', to: 'gudo', createdAt: '2021-01-05' },
  ],
  [
    { id: '7', from: 'dave', to: 'gudo', createdAt: '2021-01-05' }, // How to include this?
  ]
]
]
 

Если бы вы могли мне помочь или дать представление о лучшем способе сделать это, я был бы очень благодарен.

Ответ №1:

Если вы можете придумать способ уникальной идентификации одного ключа из заданной комбинации двух участников (независимо от from или to ), группировка в объект, индексируемый этим ключом, должна быть довольно простой.

Я бы отсортировал массив из двух свойств в алфавитном порядке (и получил, например, ['gudo', 'mimi'] ), затем выбрал символ, который не будет отображаться в свойствах from или to , затем присоединился к этому символу (например gudo#mimi ). Это может служить ключом. Затем вам просто нужно выполнить итерацию по массиву и определить ключ для каждого элемента:

 const msgs = [
  { id: '1', from: 'mimi', to: 'gudo', createdAt: '2021-01-01:T-50-249' }, //GROUP THIS
  { id: '5', from: 'gudo', to: 'mimi', createdAt: '2021-01-01:T-46-462' }, //

  { id: '2', from: 'john', to: 'gudo', createdAt: '2021-01-01:T-50-249' }, //GROUP THIS
  { id: '3', from: 'gudo', to: 'john', createdAt: '2021-01-01:T-46-462' }, //

  { id: '8', from: 'gudo', to: 'dave', createdAt: '2021-01-01:T-46-462' }, //GROUP THIS
]

const getKey = ({ from, to }) => [to, from]
  .sort((a, b) => a.localeCompare(b))
  .join('#');
const msgsByKey = {};
for (const msg of msgs) {
  const key = getKey(msg);
  if (!msgsByKey[key]) {
    msgsByKey[key] = [];
  }
  msgsByKey[key].push(msg);
}
console.log(Object.values(msgsByKey)); 

Ответ №2:

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

Ниже приведен другой подход.

 let msg = [
  { id: '2', from: 'mimi', to: 'gudo', createdAt: '2021-01-01'},
  { id: '3', from: 'gudo', to: 'mimi', createdAt: '2021-01-02' },
  { id: '5', from: 'gudo', to: 'john', createdAt: '2021-01-03' },
  { id: '4', from: 'john', to: 'gudo', createdAt: '2021-01-05' },
  { id: '7', from: 'dave', to: 'gudo', createdAt: '2021-01-05' },
]

let p = [];
let processed = [];
msg.forEach(function(m) {
  if( processed.indexOf(m.id) >= 0 ) {
    return;
  }
  let filter = msg.filter(function(_m) {
    return m.from === _m.to amp;amp; m.to === _m.from;
  });
  if( filter amp;amp; filter.length) {
    p.push([m, filter[0]]);
    processed.push(m.id);
    processed.push(filter[0].id);
  } else {
    p.push(m);
    processed.push(m.id);
  }
});

console.error(p);
 

Комментарии:

1. Действительно полезно! Спасибо за идею!