Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

All pairs in an ES6 Map

In ES6, given a Map, how would one visit pairs of values, where order is unimportant?

If this were arrays, I would do as follows:

let arr = ["a", "b", "c", "d"];

for (let i=0; i < arr.length; i++)
  for (let j=i+1; j<arr.length; j++)
    console.log(`${arr[i]},${arr[j]}`);

With Maps, I'm struggling to find a way to do something similar in an efficient and elegant manner. Iterators looked like they would do the trick, but I was assuming they would behave like C++ Standard Library iterators, where an iterator can be cloned into independent iterators.

The best I've come up with is:

var map = new Map([[0, "a"],[1, "b"],[2, "c"],[3, "d"]]);

for (let key of map.keys()) {
  let log_away = false;

  for (let other_key of map.keys()) {
    if (log_away)
        console.log(`${map.get(key)},${map.get(other_key)}`);
    else
        log_away = (key === other_key);
}

This is reasonably succinct, but having to visit all pairs, whether they will be used or not, is hardly efficient. Worse, if one were to try to adapt this to a Set containing large objects, the comparison of keys at the end would have to be a comparison of values, which could be prohibitively expensive.

like image 953
Mark Avatar asked Jan 05 '23 05:01

Mark


2 Answers

You can call the values() method and then call Array.from() on the result to get an array of all the values. Then you can do it as you do with arrays.

const map = new Map([[0, "a"],[1, "b"],[2, "c"],[3, "d"]])

const values = Array.from(map.values())
for (let i = 0; i < values.length; i++)
  for (let j = i + 1; j < values.length; j++)
    console.log(`${values[i]},${values[j]}`)
like image 139
Michał Perłakowski Avatar answered Jan 13 '23 11:01

Michał Perłakowski


To add one more loop option to the mix (not better, just an alternative): using the rest operator to always loop through the remaining entries.

let map = new Map([[0, "a"],[1, "b"],[2, "c"],[3, "d"]]);

let arr = [...map.values()] ,v;
while(arr.length > 1){
  [v,...arr] =arr;  
  arr.forEach(v2 => console.log([v,v2].join(',')));
}

or do the same in a recursive function (variable) to get an array of pairs:

let map = new Map([[0, "a"],[1, "b"],[2, "c"],[3, "d"]]);

const fn = ([v,...a]) => v ? [...a.map(v2=>[v,v2].join()),...fn(a)] : [];
console.log(fn(map.values()));
like image 33
Me.Name Avatar answered Jan 13 '23 11:01

Me.Name