2

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}
]
Dacre Denny
  • 29,664
  • 5
  • 45
  • 65
thalesGog
  • 321
  • 2
  • 11
  • 1
    So basically you want to count how many times a certain `type` has occurred? – Keno Feb 06 '19 at 23:23
  • Also, how do you want it to give the name `Disney`? What's the criteria in this case? – Keno Feb 06 '19 at 23:23
  • Yea, I want to count how many times a certain type has occur. For example, how many type 'desconto' has that object. – thalesGog Feb 06 '19 at 23:27
  • I want that the original data to be the same and mixed with the new quantity data for the items that repeated – thalesGog Feb 06 '19 at 23:29
  • So the `name` should only be from the very first one found for each `type` and just discard the other names? – Phil Feb 06 '19 at 23:30
  • 1
    _"I have tried using filter, map and reduce but didn't worked"_ can you please show your attempts. It's usually better to help you with your own code – Phil Feb 06 '19 at 23:31
  • The appropriate duplicate would be [group and count objects of array and create new array](https://stackoverflow.com/q/50913026/215552) – Heretic Monkey Feb 06 '19 at 23:36
  • @phil I tried too use them, but I don't how, so the code was trash and I delete it – thalesGog Feb 06 '19 at 23:47
  • @thalesGog Feel like answering [this question](https://stackoverflow.com/questions/54564076/how-to-count-the-number-of-object-property-value-occurrences-and-put-that-quanti#comment95927138_54564076)? – Phil Feb 06 '19 at 23:48
  • I just want to count the repeated items and keep the original data mixed with the quantity/repeated times for each item – thalesGog Feb 06 '19 at 23:49
  • That doesn't answer the question at all. Are you happy to discard the _"Bottieli"_ and _"Monster Truck"_ names simply because _"Disney"_ comes first in the array for the _"inteira"_ type? – Phil Feb 06 '19 at 23:51
  • 1
    @Phil I don't want to discard them. You're right, how can it be? – thalesGog Feb 06 '19 at 23:59
  • @KenoClayton How can I achieve the same result of your answer with more than one mapping values?] – thalesGog Feb 07 '19 at 00:00
  • @KenoClayton For example: make the new object only if matching key value of name and type were equal? – thalesGog Feb 07 '19 at 00:01
  • @thalesGog how would you want them included in the output then? Your examples aren't sufficient; you'll need to edit your question. How about in an array, eg `{type: 'inteira', names: ['Disney', 'Bottieli', 'Monster Truck'], quantity: 3}` (though `quantity` is now redundant as you can just check the `names` length) – Phil Feb 07 '19 at 00:02
  • 1
    @Phil forget about It, with the dacre Denny answer I can work It out, thanks! – thalesGog Feb 07 '19 at 00:25
  • _"I can work It out"_ that's awesome – Phil Feb 07 '19 at 00:26

1 Answers1

1

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

  • iterate your input array
  • for each iteration, reduce the input to an mapping where the key of the map is the item type, and the value is the item (with count)
  • if a value for type key is found in the mapping, increment the count of the matching item
  • if a value for type 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 item
  • Pass the mapping created by reduce() to Object.values() to extract a flat Array of the items with corresponding counts computed during the reduction

Here'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 :-)

Dacre Denny
  • 29,664
  • 5
  • 45
  • 65