如何通过属性值计算对象的出现次数,以及如何将对象的计数存储在新数组中

时间:2019-02-06 23:22:07

标签: javascript arrays ecmascript-6 counting

我想计算一个对象内部出现相同值的次数,并创建一个添加了数量的新对象。

我尝试使用filtermapreduce,但是没有用。

我有此数据:

let arrayOfObjects = [
    {name: 'Disney', type: 'inteira'},
    {name: 'Bottieli', type: 'inteira'},
    {name: 'Monster Truck', type: 'inteira'},
    {name: 'Xuxa', type: 'desconto'},
    {name: 'Pokémon', type: 'zaffari'},
]

我想要这样的输出(根据'type'键值并显示每个项目的数量,创建一个没有重复项目的新对象)

newArrayOfObjects = [
    {name: 'Disney', type: 'inteira', quantity: 3},
    {name: 'Xuxa', type: 'desconto', quantity: 1},
    {name: 'Pokémon', type: 'zaffari', quantity: 1}
]

1 个答案:

答案 0 :(得分:0)

有许多方法可以实现。一种方法是通过Array#reduce方法构造一个映射,该映射将每个type映射到具有以下内容的item数据的相应count(请注意,使用这样的映射是一种优化):

  • 迭代您的输入数组
  • 对于每次迭代,请减少对映射的输入,其中映射的key是项type,而value是项(带计数)
  • 如果在映射中找到type键的值,请增加匹配项的计数
  • 如果在映射中找不到type键的值,请在reduce()中插入要迭代的当前项的克隆,并为该项包括初始计数1
  • reduce()创建的映射传递到Object.values(),以提取平整的Array项,并在缩减过程中计算出相应的计数。

以下是一个有效的代码片段,可用于实际操作:

let arrayOfObjects = [
    {name: 'Disney', type: 'inteira'},
    {name: 'Bottieli', type: 'inteira'},
    {name: 'Monster Truck', type: 'inteira'},
    {name: 'Xuxa', type: 'desconto'},
    {name: 'Pokémon', type: 'zaffari'},
]

/* Iterate arrayOfObjects and reduce() this to a temporary mapping where item counts
are aggregated. Once that mapping is built, we'll extract values of the mapping to
get the desired array result (ie with items, and type counts) */
let newArrayOfObjects = Object.values(arrayOfObjects.reduce((mapping, item) => {
  
  /* Find exsiting item with matching item type in our mapping */
  const { [item.type]:matchingItem } = mapping;
  
  /* If matching item found, increment the count */
  if(matchingItem) {
    matchingItem.count ++;
  }
  /* Otherwise, insert item into mapping, and also include a starting count of one for it */
  else {
    mapping[ item.type ] = { ...item, count : 1 };
  }
  
  /* Return the updated mapping */
  return mapping;

},{}))

console.log(newArrayOfObjects);

希望有帮助:-)