javascript - 如何检查两个 Map 对象是否相等?

标签 javascript dictionary

我如何检查两个 ES2015 Map对象具有相同的一组 (key, value) 对?

我们可以假设所有的键和值都是原始数据类型。

解决此问题的一种方法是采用 map.entries(),从中创建数组,然后按键对该数组进行排序。对另一张 map 做同样的事情。然后循环遍历这两个数组以比较它们。由于排序(性能低效)和制作这些数组(内存效率低下),所有这些接缝都很麻烦而且效率也很低。

有没有人有更好的主意?

最佳答案

没有“标准”或“内置”的方式来做到这一点。从概念上讲,您只需比较两个 Map 对象具有相同的键和每个键的值,并且没有额外的键。

为了尽可能高效地进行比较,您可以进行以下优化:

  1. 首先检查两个 map 上的.size 属性。如果两个映射的键数不同,那么您马上就会知道,它们不可能相同。
  2. 此外,保证它们具有相同数量的键允许您只迭代其中一个映射并将其值与另一个进行比较。
  3. 使用 for (var [key, val] of map1) 迭代器语法来迭代键,这样您就不必自己构建或排序键数组(应该更快并且内存效率更高)。
  4. 然后,最后,如果您确保一旦发现不匹配就立即返回比较,那么当它们不相同时将缩短执行时间。

然后,由于 undefined 是 Map 中的合法值,但如果找不到键,它也是 .get() 返回的内容,我们必须注意为此,如果我们比较的值是 undefined,则执行额外的 .has()

由于 Map 对象的键和值本身都可以是对象,如果您想要对对象进行深入的属性比较以确定是否相等,而不只是更简单的 === Javascript 默认使用来测试同一个对象。或者,如果您只对具有键和值基元的对象感兴趣,则可以避免这种复杂性。

对于仅测试严格值相等性的函数(检查对象以查看它们是否是同一物理对象,而不是深度属性比较),您可以执行如下所示的操作。这使用 ES6 语法实现 map 对象的高效迭代,并尝试在它们不匹配时通过短路并在发现不匹配时立即返回 false 来提高性能。

"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);
}


如果您想进行深入的对象比较,而不是仅仅比较以查看它们在物理上是否是同一个对象,其中值可以是对象或数组,那么事情会变得复杂得多。

为此,您需要一种考虑以下所有因素的深度对象比较方法:

  1. 嵌套对象的递归比较
  2. 防止循环引用(可能导致无限循环)
  3. 了解如何比较某些类型的内置对象,例如 Date

由于其他地方已经写了很多关于如何进行深度对象比较的文章(包括 StackOverflow 上的许多高票答案),我认为这不是您问题的主要部分。

关于javascript - 如何检查两个 Map 对象是否相等?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35948335/

相关文章:

javascript - 如何使用 JavaScript 设置单选按钮状态

javascript - 函数不会返回值

python - 将字典数组转换为具有潜在不匹配字段名的二维数组

python - 无法显示 Vincent 示例 map ;没有建议的解决方案有效

javascript - 如何确定点击是发生在元素的滚动条上还是发生在其内容上

javascript - 如何强制浏览器(应用程序)保存自动填充的登录名和密码

python - 将两个字典中的值相乘,但一个字典中不存在一对键和值

Python数据结构模仿关系数据库

javascript - 选择 2 : Results not showing using AJAX

python - 按日期键对 python 字典进行排序