Reputation: 351
I want to count how many times the same value has occurred inside an object, and create a new object with the quantity added.
I have tried using filter
, map
and reduce
but it didn't work.
I have this data:
let arrayOfObjects = [
{name: 'Disney', type: 'inteira'},
{name: 'Bottieli', type: 'inteira'},
{name: 'Monster Truck', type: 'inteira'},
{name: 'Xuxa', type: 'desconto'},
{name: 'Pokémon', type: 'zaffari'},
]
And I want something like this output (make a new object without the repeated items based on the 'type' key value and showing the quantity of each item):
newArrayOfObjects = [
{name: 'Disney', type: 'inteira', quantity: 3},
{name: 'Xuxa', type: 'desconto', quantity: 1},
{name: 'Pokémon', type: 'zaffari', quantity: 1}
]
Upvotes: 2
Views: 1832
Reputation: 30360
There are a number of ways this can be achieved. One approach would be construct a mapping via the Array#reduce
method, which maps each type
to the corresponding item
with count
data included by the following (note that the use of a mapping like this is an optimisation):
key
of the map is the item type
, and the value
is the item (with count)type
key is found in the mapping, increment the count of the matching itemtype
key is not found in the mapping, insert a clone of the current item being iterated in reduce()
, with an initial count of 1
included for that itemreduce()
to Object.values()
to extract a flat Array
of the items with corresponding counts computed during the reductionHere's a working snippet to show this in action:
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);
Hope that helps :-)
Upvotes: 1