如何检查两个Map对象是否相等? [英] How can I check if two Map objects are equal?

查看:333
本文介绍了如何检查两个Map对象是否相等?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何检查两个 ES2015地图对象具有相同的(键,值)对的集合?

How can I check if two ES2015 Map objects have the same set of (key, value) pairs?

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

We can assume that all the keys and values are primitive datatypes.

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

One approach to solve this would be to take the map.entries(), create array from it, then sort that array by keys. And do the same thing with the other map. And then loop through those two arrays to compare them. All this seams cumbersome and also very inefficient because of sorting (performance inefficiency) and because of making those arrays (memory inefficiency).

有没有人有更好的想法?

Does anybody have better idea?

推荐答案

没有标准或内置方式来执行此操作。从概念上讲,您只需比较两个Map对象的每个键具有相同的键和值,并且没有额外的键。

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:


  1. 首先检查 .size 属性在两张地图上。如果两张地图的密钥数量不同,那么您就知道它们不能完全相同。

  2. 此外,保证它们具有相同数量的键允许您只迭代其中一个映射并将其值与另一个映射进行比较。

  3. 使用(map [1的var [key,val])迭代器语法来迭代键,这样你就不必自己构建或排序一组键(应该更快,更节省内存)。

  4. 然后,最后,如果确保在找到不匹配时立即返回比较,当它们不相同时,它会缩短执行时间。

  1. 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.
  2. 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.
  3. 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).
  4. 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.

然后,因为 undefined 是Map中的合法值,但它也是 .get()返回,如果找不到密钥,我们必须注意额外的 .has()如果我们比较的值是 undefined

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.

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

Since both keys and values with a Map object can be objects themselves, this gets much tricker 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.

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

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.

此代码段需要Firefox 41或Chrome 49.它在Edge 25或IE 11中不起作用(可能是因为类型的用户/ 正在使用的ES6语法)。它可以通过使用较旧的技术用于 for 循环在其他浏览器中工作,但是因为这已经是关于ES6功能(Map对象)了但我们是为了优化实现,我选择使用最新的ES6语法。

This snippet requires Firefox 41 or Chrome 49. It does not work in Edge 25 or IE 11 (probably because of the user of the type of for/of ES6 syntax it is using). It could be made to work in other browsers by using older tech for the for loop, but since this is already about an ES6 feature (the Map object) anyway and we're trying to optimize the implementation, I chose to use the latest ES6 syntax.

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

如果你想进行深度对象比较而不是仅仅比较它们是否在物理上是同一个对象,其中值可以是对象或数组,那么生活会变得复杂得多。

If you wanted to do deep object comparison rather than just comparing to see if they are physically the same object, where values could be objects or arrays, then life gets a lot more complicated.

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

To do that, you need a deep object comparison method that takes into account all of the following:


  1. 嵌套对象的递归比较

  2. 针对循环引用的保护(可能导致无限循环)

  3. 了解如何比较某些类型的构建在诸如日期之类的对象中。

  1. Recursive comparison for nested objects
  2. Protection against circular references (which can cause an infinite loop)
  3. Knowledge of how to compare some types of built-in objects such as a Date.

因为其他地方写了很多关于如何进行深度对象比较(包括StackOverflow上的一些高度评价的答案),我将假设这不是你问题的主要部分。

Since a lot has been written elsewhere about how to do a deep object comparison (including a number of highly voted answers here on StackOverflow), I will assume that is not the main part of your question.

这篇关于如何检查两个Map对象是否相等?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆