Merge map values

# Mohan.Radhakrishnan at cognizant.com (10 years ago)

I am using ES6 by transpiling. The features remind me of Java lambdas.

If I have a string 'mainn' then my map should contain this.

[a=1, i=1, m=1, n=2]

Java : Example. I may not need the TreeMap here.

String s = "mainn".replaceAll("[^a-z\s]", "");

final Map<Character, Integer> count = s.chars(). map(Character::toLowerCase). collect(TreeMap::new, (m, c) -> m.merge((char) c, 1, Integer::sum), Map::putAll);

What could be the es6 equivalent ?

Thanks, Mohan This e-mail and any files transmitted with it are for the sole use of the intended recipient(s) and may contain confidential and privileged information. If you are not the intended recipient(s), please reply to the sender and destroy all copies of the original message. Any unauthorized review, use, disclosure, dissemination, forwarding, printing or copying of this email, and/or any action taken in reliance on the contents of this e-mail is strictly prohibited and may be unlawful. Where permitted by applicable law, this e-mail and other e-mail communications sent to and from Cognizant e-mail addresses may be monitored.

# Mohan.Radhakrishnan at cognizant.com (10 years ago)

It could be something like this. But if this is done internall then we don't need code to explicitly manipulate the Map.

let m = new Map(); m.set("x",1); //set other keys

//for (let value of m.entries()){

//if (Object.keys(m).every((key) => m[key] == value[key])){
    //Merge
//}

//} }

Thanks, Mohan

From: Radhakrishnan, Mohan (Cognizant) Sent: Tuesday, April 28, 2015 2:23 PM To: 'es-discuss at mozilla.org' Subject: Merge map values

Hi,

I am using ES6 by transpiling. The features remind me of Java lambdas.

If I have a string 'mainn' then my map should contain this.

[a=1, i=1, m=1, n=2]

Java : Example. I may not need the TreeMap here.

String s = "mainn".replaceAll("[^a-z\s]", "");

final Map<Character, Integer> count = s.chars(). map(Character::toLowerCase). collect(TreeMap::new, (m, c) -> m.merge((char) c, 1, Integer::sum), Map::putAll);

What could be the es6 equivalent ?

Thanks, Mohan This e-mail and any files transmitted with it are for the sole use of the intended recipient(s) and may contain confidential and privileged information. If you are not the intended recipient(s), please reply to the sender and destroy all copies of the original message. Any unauthorized review, use, disclosure, dissemination, forwarding, printing or copying of this email, and/or any action taken in reliance on the contents of this e-mail is strictly prohibited and may be unlawful. Where permitted by applicable law, this e-mail and other e-mail communications sent to and from Cognizant e-mail addresses may be monitored.

# Axel Rauschmayer (10 years ago)

The best I can come up with is a totally different, less functional approach:

const s = 'mainn';
let map = new Map();
for (let ch of s) {
    ch = ch.toLowerCase();
    const prevCount = map.get(ch) || 0;
    map.set(ch, prevCount+1);
}
# Kevin Smith (10 years ago)

Another option:

var map = new Map;
Array.from("mainn")
  .map(c => c.toLowerCase())
  .forEach(c => map.set(c, (map.get(c) | 0) + 1));

This kind of question is probably better left for StackOverflow, however.

# Andrea Giammarchi (10 years ago)

Not sure why everyone went for the Map version when in JS every object is basically the equivalent of a Map already :-)

let m = Array.from("mainn").reduce((m,k) => ((m[k] = 1 + (m[k] | 0)), m),
{});

looks a win to me, if you need to check or drop chars from the string I would probably do it once before passing that to Array.from

Agreed with Kevin this is rather a StackOverflow like question :-)

Best

# Mohan.Radhakrishnan at cognizant.com (10 years ago)

I agree this is not about the ES6 spec. But the answers helped because I was trying to understand ES6’s arrow function that is similar to lambdas.

Thanks.

From: Andrea Giammarchi [mailto:andrea.giammarchi at gmail.com] Sent: Tuesday, April 28, 2015 6:02 PM To: Kevin Smith Cc: Axel Rauschmayer; Radhakrishnan, Mohan (Cognizant); es-discuss list Subject: Re: Merge map values

Not sure why everyone went for the Map version when in JS every object is basically the equivalent of a Map already :-)

let m = Array.from("mainn").reduce((m,k) => ((m[k] = 1 + (m[k] | 0)), m), {});

looks a win to me, if you need to check or drop chars from the string I would probably do it once before passing that to Array.from

Agreed with Kevin this is rather a StackOverflow like question :-)

Best

On Tue, Apr 28, 2015 at 1:19 PM, Kevin Smith <zenparsing at gmail.com<mailto:zenparsing at gmail.com>> wrote:

Another option:

var map = new Map;
Array.from("mainn")
  .map(c => c.toLowerCase())
  .forEach(c => map.set(c, (map.get(c) | 0) + 1));

This kind of question is probably better left for StackOverflow, however.

# Axel Rauschmayer (10 years ago)

With Maps, there are less pitfalls. For example: what if you want to use your version to count words and one of the words is __proto__? Most pitfalls can be fixed via Object.create(null), but Maps are more straightforward for data (vs. code).

But your version can be easily adapted to Maps, I like the way you use reduce(). The | should be a ||.

# Andrea Giammarchi (10 years ago)

Now you read again the "exercise" and realize that's impossible to have as a piutfall ... no, I just used a KISS approach for what I can tell, no pitfalls with one single surrogate could happen by specs.

Best

# Andrea Giammarchi (10 years ago)

Moreover undefined|0 is exactly 0. The |0 is used in asm.js because it explicitly declares the intent.

So again, no error in there ;-)

# Andrea Giammarchi (10 years ago)

Sorry Axel, I was rushing, it sounded over-rude ... so, yes, Map are better for words, but in this specific case it was about all chars/surrogate pairs, that's why I've said Objects where safe ... plus the rest, reduce also is very handy for this exact kind of things ;-)

But yes, if it was a owrd counter, I'd use same logic with new Map passed instead of {} and the correct .set/.get invoke

Best

# Jordan Harband (10 years ago)

Would new Map(maps.reduce((e, m) => e.concat(Array.from(m)), [])) not

create a new Map from merging an array of maps? (It relies on the Map.prototype.[Symbol.iterator] which is Map#entries, and the iterable argument of the Map constructor)