通过ES6中的项目键减少数组

时间:2018-06-24 15:05:17

标签: javascript arrays object ecmascript-6 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 }
];

我试图实现的是减少此数组,使其看起来像这样:

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): Reduce array based on object attribute,但看不出来。

6 个答案:

答案 0 :(得分:10)

您可以将数组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);

答案 1 :(得分:6)

您可以使用数组作为累加器并查找具有所需名称的插入对象,以添加实际计数。如果找不到,请添加新对象。

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; }

答案 2 :(得分:6)

您可以尝试An unhandled exception of type 'System.Exception' occurred in Emgu.CV.World.dll Additional information: Unsupported conversion 喜欢

reduce()

答案 3 :(得分:2)

还有另一个(略有不同)解决方案

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);

答案 4 :(得分:1)

您可以使用哈希表建立resultig数组:

values

答案 5 :(得分:1)

您可以使用一个简单的forEach方法,如下所示:

const res = {};

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

res将包含您的预期结果。