0

Suppose to have two Map objects, how to check if their keys sets are the same?

For example:

const A = new Map();
A.set('x', 123);
A.set('y', 345);

const B = new Map();
B.set('y', 567);
B.set('x', 789);

const C = new Map();
C.set('x', 121);
C.set('y', 232);
C.set('z', 434);

in this case both A and B maps have the same key set (which is ['x', 'y']), while the key set of C is different since it has the extra key z.

5
  • Do you mean stackoverflow.com/questions/14368596/… ? Commented Aug 26, 2018 at 20:06
  • you cannot call .keys().size() on a Map object Commented Aug 26, 2018 at 20:08
  • @SuperDJ being specific to Map I don't think this question is same, mainly the way of answers will be different Commented Aug 27, 2018 at 9:48
  • 1
    @FrancescoBorzì may I inquire as to the reason why you accepted my long and clunky answer instead of these others that look shorter / cleaner? (Only thing I can come up with is the complexity of the answer, mine looks more like self-explaining pseudo code) Commented Aug 27, 2018 at 10:01
  • 1
    because it's the most self-explaining answer :D Commented Aug 27, 2018 at 10:22

7 Answers 7

5

Check that each map's size is the same, and then iterate over the keys of one Map and check that the key exists in the other as well. Utilizing Array.prototype.every.call means that there's no need to create an intermediate array:

const A = new Map();
A.set('x', 123);
A.set('y', 345);

const B = new Map();
B.set('y', 567);
B.set('x', 789);

const C = new Map();
C.set('x', 121);
C.set('y', 232);
C.set('z', 434);

const sameKeySet = (m1, m2) => (
  m1.size === m2.size
  && Array.prototype.every.call(m1.keys(), key => m2.has(key))
);
console.log(sameKeySet(A, B));
console.log(sameKeySet(A, C));

Sign up to request clarification or add additional context in comments.

3 Comments

Well, that looks certainly cleaner than mine. Is there a reason to use Array.prototype instead of []. Also can't you drop the (... && ...) brackets around the condition?
Utilizing Array.prototype.every.call means that there's no need to create an intermediate array, whereas something like [...m1.keys()] would unnecessarily create a new Array from the iterator. Yes, it would be syntactically valid to drop the parentheses, but because it's a multi-line expression, I think the parentheses make the code clearer to read.
Ah ok, I was thinking about [].every.call hoping that an empty array wouldn't be that much of a problem and it wouldn't look "so scary" as the Array.prototype =) [actually I only wanted to golf it down to two lines]
1

You could check the size and then iterate over the keys of one map and check that the other one has them too.

const A = new Map();
A.set('x', 123);
A.set('y', 345);

const B = new Map();
B.set('y', 567);
B.set('x', 789);

const C = new Map();
C.set('x', 121);
C.set('y', 232);
C.set('z', 434);

function sameKeys(a, b) {
  if (a.size != b.size) {
    return false;
  }

  for (let key in a.keys()) {
    if (!b.has(key)) {
      return false;
    }
  }

  return true;
}

console.log(sameKeys(A, B));
console.log(sameKeys(A, C));

Comments

1

You can convert the keys of a Map into an array by spreading the iterator returned by the keys() method:

const aKeys = [...A.keys()];

Then you just will have to compare all the keys arrays. For the case you show up, you can simple do:

const A = new Map();
A.set('x', 123);
A.set('y', 345);

const B = new Map();
B.set('y', 567);
B.set('x', 789);

const C = new Map();
C.set('x', 121);
C.set('y', 232);
C.set('z', 434);

const aKeys = [...A.keys()];
const bKeys = [...B.keys()];
const cKeys = [...C.keys()];

console.log(aKeys.sort().toString() == bKeys.sort().toString());
console.log(aKeys.sort().toString() == cKeys.sort().toString());
console.log(bKeys.sort().toString() == cKeys.sort().toString());

Comments

1

Basically you need to check for two things:

  1. Size of both the maps, if they are unequal than simply return false.
  2. If size is same than check if all the keys of map1 are present in map2,if they are than return true else return false.

const A = new Map();
A.set('x', 123);
A.set('y', 345);

const B = new Map();
B.set('y', 567);
B.set('x', 789);

const C = new Map();
C.set('x', 121);
C.set('y', 232);
C.set('z', 434);

const D = new Map();
C.set('x', 121);
C.set('z', 232);


function isSame(a,b){
  if(a.size != b.size)
    return false;
 for(const [key, value] of a.entries()){
    if(!b.has(key))
      return false;
  }
  return true;
}
console.log(isSame(A,B));
console.log(isSame(A,C));
console.log(isSame(A,D));

Comments

1

You could check the size and take the prototype of has and the second map as thisArg for checking all keys with Array#some.

This works for any types, because it does not mutate the type of the keys.

const
    compare = (a, b) => a.size === b.size && [...a.keys()].some(Map.prototype.has, b),
    a = new Map([['x', 123], ['y', 345]]);
    b = new Map([['y', 567], ['x', 789]]);
    c = new Map([['x', 121], ['y', 232], ['z', 434]]);

console.log(compare(a, b));
console.log(compare(a, c));

Comments

0

You can construct a new Map with both of their entries, and then compare size. Anyway you need to check the size of both of them and if its same then only you should proceed for this.

map1.size.size === map2.size &&

new Map([...map1, ...map2])).size === map1.size //or map2.size

Let's create a working example:

const A = new Map();
A.set('x', 123);
A.set('y', 345);

const B = new Map();
B.set('y', 567);
B.set('x', 789);

const C = new Map();
C.set('x', 121);
C.set('y', 232);
C.set('z', 434);

let compareMap = (m1, m2) => (
  m1.size === m2.size &&
  (new Map([...m1, ...m2])).size === m1.size
)

console.log('Compare A & B: ', compareMap(A, B));
console.log('Compare A & C: ', compareMap(A, C));
console.log('Compare B & C: ', compareMap(B, C));

2 Comments

In case you didn't know: Code-Snippets have an inbuild autoformat button: i.sstatic.net/RwGHH.png
Thanks for the alignment edit. However, people should focus on the content (at least when it's 2-liner) but yes, alignment dose matter to a better have visibility of the actual content!
0

Here's a one liner wrapped in a TypeScript'ized function

function sameKeys(a: Map<string, string>, b: Map<string, string>): boolean {
    return a.size === b.size && [...a.keys()].every(key => b.has(key))
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.