There is no "standard" or "built-in" way to do this. Conceptually, you just have to compare that the two Map objects have the same keys and values for each key and have no extra keys.
To be as efficient about the comparison as possible, you can do the following optimizations:
- First check the
.size
property on both maps. If the two maps don't have the same number of keys, then you know right away, they can't be identical.
- Furthermore, guaranteeing that they have the same number of keys allows you to just iterate one of the maps and compare its values to the other.
- Use the
for (var [key, val] of map1)
iterator syntax for iterating the keys so you don't have to build or sort an array of keys yourself (should be both faster and more memory efficient).
- Then, lastly, if you make sure that the comparison returns immediately as soon as a mismatch is found, then it will shorten the execution time when they are not the same.
Then, since undefined
is a legal value in a Map, but it's also what .get()
returns if the key is not found, we have to watch out for that by doing an extra .has()
if the value we're comparing is undefined
.
Since both keys and values with a Map object can be objects themselves, this gets much trickier if you want a deep property comparison of objects to determine equality rather than just the more simple ===
that Javascript uses by default to test for the same object. Or, if you're only interested in objects that have primitives for keys and values, then this complexity can be avoided.
For a function that tests only strict value equality (checks objects to see if they are the same physical object, not a deep property comparison), you can do what is shown below. This uses ES6 syntax for efficient iteration of the map objects and attempts to improve performance when they do not match by short circuiting and returning false
as soon as a mismatch is found.
"use strict";
function compareMaps(map1, map2) {
var testVal;
if (map1.size !== map2.size) {
return false;
}
for (var [key, val] of map1) {
testVal = map2.get(key);
// in cases of an undefined value, make sure the key
// actually exists on the object so there are no false positives
if (testVal !== val || (testVal === undefined && !map2.has(key))) {
return false;
}
}
return true;
}
// construct two maps that are initially identical
var o = {"k" : 2}
var m1 = new Map();
m1.set("obj", o);
m1.set("str0", undefined);
m1.set("str1", 1);
m1.set("str2", 2);
m1.set("str3", 3);
var m2 = new Map();
m2.set("str0", undefined);
m2.set("obj", o);
m2.set("str1", 1);
m2.set("str2", 2);
m2.set("str3", 3);
log(compareMaps(m1, m2));
// add an undefined key to m1 and a corresponding other key to m2
// this will pass the .size test and even pass the equality test, but not pass the
// special test for undefined values
m1.set("str-undefined", undefined);
m2.set("str4", 4);
log(compareMaps(m1, m2));
// remove one key from m1 so m2 has an extra key
m1.delete("str-undefined");
log(compareMaps(m1, m2));
// add that same extra key to m1, but give it a different value
m1.set("str4", 5);
log(compareMaps(m1, m2));
function log(args) {
var str = "";
for (var i = 0; i < arguments.length; i++) {
if (typeof arguments[i] === "object") {
str += JSON.stringify(arguments[i]);
} else {
str += arguments[i];
}
}
var div = document.createElement("div");
div.innerHTML = str;
var target = log.id ? document.getElementById(log.id) : document.body;
target.appendChild(div);
}
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…