Группировка объектов в массиве

164
04 марта 2019, 22:30

Имеется, например, несколько объектов в массиве:

let shop = [{ 
  id: 105, 
  date: '2018-10-11', 
  fact: 100, 
  plan: 95 
}, { 
  id:105, 
  date: '2018-10-12', 
  fact: 105, 
  plan: 100 
}, { 
  id:106, 
  date: '2018-10-11', 
  fact: 110, 
  plan: 115 
}, { 
  id:106, 
  date: '2018-10-12', 
  fact: 120, 
  plan: 115 
}];

Нужно получить структуру из объектов с id и массивами факта и плана (выполнения продаж, например):

let groups = [{ 
  id: 105, 
  fact: [100, 105], 
  plan : [95, 100] 
}, { 
  id: 106, 
  fact: [110, 120], 
  plan: [115, 115] 
}]; 
 
console.log(groups);

Пытался использовать reduce, но тогда я складываю вообще все факты и планы, не учитывая id. Прогонял первый массив в forEach и map, но так же не могу понять, как мне оставить id уникальным, а fact и plan слить в массивы к этим id.

Answer 1
  • Проходим по всем элементам shops
  • Для каждого элемента ищем уже существующую группу по id
  • Если группа найдена - добавляем в её списки fact и plan соответствующие значения элемента
  • Иначе создаём новую группу со значениями из элемента и добавляем её в список групп

Реализации могут несколько отличаться, но суть такова:

let shop = [{ 
  id: 105, 
  fact: 100, 
  plan: 95 
}, { 
  id: 105, 
  fact: 105, 
  plan: 100 
}, { 
  id: 106, 
  fact: 110, 
  plan: 115 
}, { 
  id: 106, 
  fact: 120, 
  plan: 115 
}]; 
 
let groups = []; 
 
for (let element of shop) { 
  let existingGroups = groups.filter(group => group.id == element.id); 
  if (existingGroups.length > 0) { 
    existingGroups[0].fact.push(element.fact); 
    existingGroups[0].plan.push(element.plan); 
  } 
  else { 
    let newGroup = { 
      id: element.id, 
      fact: [element.fact], 
      plan: [element.plan] 
    }; 
    groups.push(newGroup); 
  } 
} 
 
console.log(groups);

Answer 2

Для группировки можно воспользоваться методом reduce.

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

let shop = [{ 
  id: 105, 
  date: '2018-10-11', 
  fact: 100, 
  plan: 95 
}, { 
  id:105, 
  date: '2018-10-12', 
  fact: 105, 
  plan: 100 
}, { 
  id:106, 
  date: '2018-10-11', 
  fact: 110, 
  plan: 115 
}, { 
  id:106, 
  date: '2018-10-12', 
  fact: 120, 
  plan: 115 
}]; 
var map = shop.reduce((acc, cur)=>{ 
acc[cur.id] = acc[cur.id] || {  
  id: cur.id, 
  facts: [], 
  plans: [] 
}; 
acc[cur.id].plans.push(cur.plan); 
acc[cur.id].facts.push(cur.fact); 
return acc; 
},{}) 
 
var result = Object.values(map); 
 
console.log(result);

READ ALSO
Next и prev в меню

Next и prev в меню

Есть меню, есть кнопки управления next и prevИдея такая: при клике на пункт меню срабатывает определенное событие (например, фильтрация на клиенте)...

187
Закрытие меню по клику вне блока на vanila js

Закрытие меню по клику вне блока на vanila js

Помогите реализовать закрытие меню по клику вне блока на чистом Java Script везде примеры только на JQ, я стараюсь максимально обходиться без него

183
Асинхронность callback с return и throw

Асинхронность callback с return и throw

Подскажите пожалуйста минусы использования callback (помимо основных лапша в коде), и почему мы не можем использовать return и throw с callbackами (помимо...

180
JavaScript Оператор return

JavaScript Оператор return

Задача: вернуть средний символ словаЕсли длина слова нечетна, верните средний символ

182