Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to return a ES6 Map Object after using reduce() to count instances of values in an array?

Tags:

I'm just beginning to learn JavaScript and this is a part of my Take-home exam, and the requirement is quite tricky for me.

We have many ways to counting instances of values in an object in JS, but in here I have to achieve it by calling reduce() and return an ES6 map object.

Here is the requirement:

/**
* Takes an array of items, and returns a Map with the
* frequencies (counts) of each item in the array.
*
* Must do this by using a single call to reduce.
*
* For example,
*  freqs([1, 2, 3, 2, 7, 2, 1]) returns Map {1 => 2, 2 => 3, 3 => 1, 7 => 1}
*  freqs("One fish two fish red fish blue fish".split(' '))
*  returns Map {"One" => 1, "fish" => 4, "two" => 1, "red" => 1, "blue" => 1}
*/

And here's my code so far:

function freqs(items) {
  var map = new Map();
  return items.reduce(function(allkey, key) {
    if (map.has(key)) {
      var value = map.get(key);
      map.set(key, value++);
    } else {
      map.set(key, 1);
    }
    return map;
  }, {})
}

I used debugger and found out that on map.set(key, value++) is not overwriting the new value in the map when it iterates. Why?

So when I input C = [1,2,3,2,7,2,1]; the output is always like this:

Map(4) {1 => 1, 2 => 1, 3 => 1, 7 => 1}

Any suggestions?

like image 528
Travis Su Avatar asked Oct 12 '17 00:10

Travis Su


1 Answers

The problem with your code is that a++ returns the value of a before adding 1:

var a = 1;
console.log(a++);
console.log(a);

Since Map#set returns the map after being modified, you can simplify your code like this:

function freqs(items) {
  return items.reduce(
    (map, e) => map.set(e, (map.get(e) || 0) + 1),
    new Map()
  );
}

Alternatively, you may use the somewhat obscure and rarely seen increment operator prefix, which also increments the variable, but returns the incremented new version of it:

var a = 1;
console.log(++a);
console.log(a);
like image 55
ichigolas Avatar answered Oct 11 '22 14:10

ichigolas