Уменьшить массив его ключ элементов в ES6 - PullRequest
0 голосов
/ 24 июня 2018

У меня есть множество фруктов:

const fruits = [
  { name: 'apple', count: 2 },
  { name: 'apple', count: 4 },
  { name: 'banana', count: 5 },
  { name: 'apple', count: 3 },
  { name: 'apple', count: 4 },
  { name: 'apple', count: 1 },
  { name: 'banana', count: 3 },
  { name: 'apple', count: 1 },
  { name: 'orange', count: 2 }
];

Я пытаюсь уменьшить этот массив, чтобы он выглядел так:

let fruitsReduces = [
  { name: 'apple', count: 15 },
  { name: 'banana', count: 8 },
  { name: 'orange', count: 2 }
];

Я сделал это, используя очень уродливый цикл for:

for (let i = 0; i < fruits.length; i++) {
  fruitItem = {};
  fruitItem.name = fruits[i].name;
  fruitItem.count = fruits[i].count;

  const fruitAlreadyInTheArray = fruitsReduced.find(fruit => fruit.name === fruitItem.name);
  if (!fruitAlreadyInTheArray) {
    fruitsReduced.push(fruitItem);
  } else {
    fruitAlreadyInTheArray.count += fruitItem.count;
  }
}

Но я уверен, что то же самое можно сделать как-нибудь с помощью ES6 array.reduce. Вы можете мне помочь? Я посмотрел на JS (ES6): уменьшить массив на основе атрибута объекта , но не могу понять.

Ответы [ 6 ]

0 голосов
/ 27 июня 2018

Вы можете использовать простой метод forEach, например:

const res = {};

fruits.forEach((e) => res[e.name] = (res[e.name] || 0) + e.count);

res будет содержать ваш ожидаемый результат.

0 голосов
/ 24 июня 2018

Еще одно (немного другое) решение

const fruits = [ 
  { name: 'apple', count: 2 }, 
  { name: 'apple', count: 4 }, 
  { name: 'banana', count: 5 }, 
  { name: 'apple', count: 3 }, 
  { name: 'apple', count: 4 }, 
  { name: 'apple', count: 1 }, 
  { name: 'banana', count: 3 },
  { name: 'apple', count: 1 }, 
  { name: 'orange', count: 2 } ];

const reduced = Object.entries ( 
  fruits.reduce( (p, o) => 
    p[o.name] ? (p[o.name] += o.count, p) : {...p, ...{[o.name]: o.count}}, {} ) )
  .map(([key, value]) => ({name: key, count: value}));

console.log(reduced);
0 голосов
/ 24 июня 2018

Можно попробовать reduce(), как

const fruits = [
  { name: 'apple', count: 2 },
  { name: 'apple', count: 4 },
  { name: 'banana', count: 5 },
  { name: 'apple', count: 3 },
  { name: 'apple', count: 4 },
  { name: 'apple', count: 1 },
  { name: 'banana', count: 3 },
  { name: 'apple', count: 1 },
  { name: 'orange', count: 2 }
];

function getReduced(total, {name,count}) {
    total[name] = total[name] || {name,count: 0};
    total[name].count += count;
    return total;
}

let fruitsReduces = Object.values(fruits.reduce(getReduced,{}));
console.log(fruitsReduces);
0 голосов
/ 24 июня 2018

Вы можете использовать хеш-таблицу для построения массива resultig:

 const result = [], hash = {};

for(const {name, count} of fruits) {
  if(hash[name]) {
     hash[name].count += count;
   } else {
     result.push(hash[name] = {name, count});
  }
}
0 голосов
/ 24 июня 2018

Вы можете использовать reduce() массив в объекте. Используйте Object.values() для преобразования объекта в массив.

const fruits = [{"name":"apple","count":2},{"name":"apple","count":4},{"name":"banana","count":5},{"name":"apple","count":3},{"name":"apple","count":4},{"name":"apple","count":1},{"name":"banana","count":3},{"name":"apple","count":1},{"name":"orange","count":2}];

var result = Object.values(fruits.reduce((c, {name,count}) => {
  c[name] = c[name] || {name,count: 0};
  c[name].count += count;
  return c;
}, {}));

console.log(result);
0 голосов
/ 24 июня 2018

Вы можете использовать массив в качестве аккумулятора и поиска для вставленного объекта с требуемым именем для добавления фактического количества. Если не найдено, добавьте новый объект.

const
    fruits = [{ name: 'apple', count: 2 }, { name: 'apple', count: 4 }, { name: 'banana', count: 5 }, { name: 'apple', count: 3 }, { name: 'apple', count: 4 }, { name: 'apple', count: 1 }, { name: 'banana', count: 3 }, { name: 'apple', count: 1 }, { name: 'orange', count: 2 }],
    result = fruits.reduce((r, { name, count }) => {
        var item = r.find(o => o.name === name);
        if (!item) {
            item = { name, count: 0 };
            r.push(item);
        }
        item.count += count;
        return r;
    }, []);
    
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Другой подход - сначала собрать все значения с помощью Map и отобразить требуемый массив с помощью Array.from и функцию отображения, которая создает новые объекты.

const
    fruits = [{ name: 'apple', count: 2 }, { name: 'apple', count: 4 }, { name: 'banana', count: 5 }, { name: 'apple', count: 3 }, { name: 'apple', count: 4 }, { name: 'apple', count: 1 }, { name: 'banana', count: 3 }, { name: 'apple', count: 1 }, { name: 'orange', count: 2 }],
    result = Array.from(
        fruits.reduce(
            (m, { name, count }) => m.set(name, (m.get(name) || 0) + count),
            new Map
        ),
        ([name, count]) => ({ name, count })
    );

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