Удалите дубликаты объектов из массива, но также увеличьте их количество

#javascript #arrays #object

Вопрос:

У меня есть этот список:

 const list = [
  { name: 'AA', quantity: 1 },
  { name: 'AA', quantity: 1 },
  { name: 'BB', quantity: 1 },
  { name: 'CC', quantity: 1 },
  { name: 'CC', quantity: 2 },
]
 

И результат, который я ищу, должен выглядеть так:

 const newlist = [
  { name: 'AA', quantity: 2 },
  { name: 'BB', quantity: 1 },
  { name: 'CC', quantity: 3 },
]
 

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

 const setObj = new Set()
const result = list.reduce((acc, item) => {
  if (!setObj.has(item.name)) {
    setObj.add(item.name)
    acc.push({ name: item.name, quantity: item.quantity })
  }

  // for (const iterator of list) {
  //   if (setObj.has(item.name)) {
  //     console.log('🚀 ~ file: Untitled-1 ~ line 15 ~ iterator', iterator)
  //   }
  // }

  console.log()
  return acc
}, [])
 

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

1. Когда вы толкаете объект, делайте quantity: item.quantity * list.filter(i=> i.name === item.name).length это .

2. Попробовал, но получил { имя: ‘AA’, количество: 2}, {имя: ‘BB’, количество: 1}, { имя: ‘CC’, количество: 2 } cc должно быть 3

3. Ах, верно, потому quantity что это не обязательно 1 все время. Да, вам придется подвести итоги, и в этот момент вы могли бы с тем же успехом reduce ответить за все это.

Ответ №1:

Вы можете использовать reduce затем найти элемент в массиве результатов, если он не существует push array , в противном add случае текущий элемент quantity element , который был найден в результате array .

Код:

 const list=[{name:"AA",quantity:1},{name:"AA",quantity:1},{name:"BB",quantity:1},{name:"CC",quantity:1},{name:"CC",quantity:2}];

const res = list.reduce((acc, e) => {
  const found = acc.find(x => e.name === x.name)
  found ? found.quantity  = e.quantity : acc.push(e)
  return acc
}, [])

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

Ответ №2:

Несколько иной подход к объекту, который использует Object.values() для возврата результирующего массива

 const list = [
  { name: 'AA', quantity: 1 },
  { name: 'AA', quantity: 1 },
  { name: 'BB', quantity: 1 },
  { name: 'CC', quantity: 1 },
  { name: 'CC', quantity: 2 },
]

const group = {};

list.forEach(e => {    
   const o =  group[e.name] = group[e.name] || {...e, quantity: 0}
   o.quantity  = e.quantity
})

const res = Object.values(group)
console.log(res) 

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

1. я дам этот ответ как лучший, потому что я заметил, что количество для других также увеличивается после многократного использования.

Ответ №3:

Вы можете выполнить цикл, чтобы либо создать новую запись, либо увеличить текущую:

 let newList = [];
list.forEach((e)=>{
   let el=newList.find(n => n.name==e.name);
   if (el) el.quantity =e.quantity;
   else newList.push(e);
});
 

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

1. Не используйте map при побочных эффектах. map возвращает преобразованный массив. Используйте его или используйте forEach вместо него.

2. да, спасибо, это то, что мне нужно, кроме того, я буду использовать forEach спасибо вам обоим

3. Зачем дважды использовать функцию find() для одного и того же элемента массива?

4. Потому что так было проще печатать :P. Я все исправил.

Ответ №4:

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

 const list = [
  { name: 'AA', quantity: 1 },
  { name: 'AA', quantity: 1 },
  { name: 'BB', quantity: 1 },
  { name: 'CC', quantity: 1 },
  { name: 'CC', quantity: 2 },
];

const filtered = list.reduce((tally, e) => {
  if (!tally[e.name]) tally[e.name] = 0;
  tally[e.name]  = e.quantity
  return tally;
}, {});

 

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

1. Я совершенно уверен, что хотел получить массив объектов, а не объект с уникальными ключами, но это близко

2. Это, по сути, функция Object.entries (), но вы также можете выполнить итерацию forEach, упомянутую в другом ответе.