两个相等数组的比较失败

时间:2023-01-16 11:32:43

Usually, addressing * community I try to describe my problem as well as I know.
But for now it is very hard to tell anything. Just look at the following picture:

通常,解决*社区我试图描述我的问题以及我知道。但是现在很难说清楚。请看下面的图片:

两个相等数组的比较失败

In general, colors is changed many times in many ways; while initial is constant and it is used to check, whether the current state is equal to initial one (and to cancel all changes, if not).
The question looks easy, but I've stuck with it. How could it be possible, that two equal arrays are not always equal?

一般来说,颜色在很多方面都会发生多次变化;而initial是常量,用于检查当前状态是否等于初始状态(如果没有,则取消所有更改)。问题看起来很简单,但我坚持下去。怎么可能,两个相等的数组并不总是相等?

I don't know what to add without bringing the code of whole project, – so just ask and I will answer.

我不知道在没有带整个项目代码的情况下添加什么, - 所以请问我会回答。

5 个解决方案

#1


2  

Arrays in ECMAscript are also just a specialised form of Object. That in turn means, if you compare array1 with array2 using == or === you're comparing effectively two object references, not the array itself nor their contents.

ECMAscript中的数组也只是Object的一种特殊形式。这反过来意味着,如果你使用==或===比较array1和array2,你有效地比较了两个对象引用,而不是数组本身及其内容。

Actually, your second approach by joining the arrays and compare that outcome is not bad, if you can guarantee that the contents are always strings. Otherwise you would have to loop the array, compare each value individually and of course also compare the .length of those arrays.

实际上,如果可以保证内容始终是字符串,那么加入数组并比较结果的第二种方法也不错。否则你必须循环数组,单独比较每个值,当然还要比较这些数组的.length。

#2


2  

JavaScript object comparisons (including comparisons between array objects) merely compare the reference values. Two different objects are never equal to each other, no matter what they look like.

JavaScript对象比较(包括数组对象之间的比较)仅比较参考值。两个不同的对象永远不会彼此相等,无论它们看起来如何。

You can of course write your own array comparison function based on your own criteria for what it means for one array to be equal to another. If the arrays should contain the same values in the same order to be considered equal, for example, then:

您当然可以根据自己的标准编写自己的数组比较函数,以确定一个数组与另一个数组相等。例如,如果数组应包含相同顺序的相同值以使其相等,则:

function arraysEq(a1, a2) {
  if (a1.length != a2.length) return false;
  for (var i = 0; i < a1.length; ++i)
    if (a1[i] !== a2[i]) return false;
  return true;
}

Note that that's just an example; it should not be considered a general solution to the "how do I compare two arrays" problem.

请注意,这只是一个例子;它不应该被认为是“如何比较两个数组”问题的一般解决方案。

#3


2  

The == operator in Javascript does not compare the contents of two arrays or objects. Instead, it just compares to see if the two arrays or objects are actually the same object. You can make your own comparison function if you want to see if the two contain the same contents. One possible way of doing that for arrays that contain strings would be with .join():

Javascript中的==运算符不会比较两个数组或对象的内容。相反,它只是比较两个数组或对象是否实际上是同一个对象。如果要查看两者是否包含相同的内容,可以创建自己的比较功能。对包含字符串的数组执行此操作的一种可能方法是使用.join():

colors.join("") === initial.join("")

This isn't entirely foolproof for all possible array contents, but if you know the array only contains strings and the strings won't contain commas themselves, then this works as a shortcut. A more robust content comparison can also be written. For a one level deep comparison of arrays, you can use this:

对于所有可能的数组内容,这并非完全万无一失,但是如果您知道数组只包含字符串并且字符串本身不包含逗号,那么这将作为快捷方式。还可以编写更强大的内容比较。对于数组的一级深度比较,您可以使用:

function compareArrays(a, b) {
    if (typeof a.length === "number" && a.length === b.length) {
        for (var i = 0; i < a.length; i++) {
            if (a[i] !== b[i]) {
                return false;
            }
        }
        return true;
    }
    return false;
}

For a deep comparison where each array could contain other arrays or objects that you also want to compare the contents of those, then you'd need a recursive solution that could deep compare both object properties and array elements.

对于每个数组可能包含其他数组或对象的深度比较,您还需要比较其中的内容,那么您需要一个可以深入比较对象属性和数组元素的递归解决方案。

You can do a deep comparison of both objects and arrays with something like this:

您可以使用以下内容对对象和数组进行深入比较:

function compareObjects(a, b) {
    // if both are objects, then do a deep comparison of all properties
    if (typeof a === "object" && typeof b === "object") {
        var aKeys = Object.keys(a).sort(), bKeys = Object.keys(b).sort();
        var prop;
        if (!compareArrays(aKeys, bKeys)) {
            return false;
        }
        // here we know the two objects have the same keys, check values now
        for (var i = 0; i < aKeys.length; i++) {
            prop = aKeys[i];
            if (typeof a[prop] === "object" && typeof b[prop] === "object") {
                if (!compareObjects(a[prop], b[prop])) {
                    return false;
                }
            } else if (a[prop] !== b[prop]) {
                return false;
            }
        }
        return true;
    } else {
        // not both objects so just do straight equality
        return a === b;
    }
}

function compareArrays(a, b) {
    if (typeof a.length === "number" && a.length === b.length) {
        for (var i = 0; i < a.length; i++) {
            if (a[i] !== b[i]) {
                return false;
            }
        }
        return true;
    }
    return false;
}

This would allow you to compare nested structures that have objects inside of them and to compare plain objects in addition to arrays like this:

这将允许您比较在其中包含对象的嵌套结构,并比较除了这样的数组之外的普通对象:

var a = {foo: [1,2,3,["a","b","c"]], fee: {a: "1"}};
var b = {fee: {a: "1"}, foo: [1,2,3,4,["a","b","c"]]};

Note: This compares publicly enumerable properties of objects or arrays. It does not compare private (e.g. closure) variables of a custom formed object (say a constructor that creates a closure). For those, the only way to compare those is with a custom comparison method that can access the private data of the objects themselves.

注意:这会比较对象或数组的公开可枚举属性。它不比较自定义形成对象的私有(例如闭包)变量(比如创建闭包的构造函数)。对于那些,比较它们的唯一方法是使用自定义比较方法,该方法可以访问对象本身的私有数据。

Note: This does not work for objects or arrays that contain circular references (DOM objects are notorious for circular references). It is possible to make it work with circular references by keeping a track of all references that are already being compared in an array or Set and not recursing into them again if already in the process of comparing them.

注意:这不适用于包含循环引用的对象或数组(DOM对象因循环引用而臭名昭着)。通过跟踪已经在数组或集合中进行比较的所有引用,并且如果已经在比较它们的过程中再次递归它们,可以使它与循环引用一起工作。

#4


1  

In JavaScript we have [] === []; // false because all Objects are tested for equality by their reference, you can see the spec on this here (7) and here (1.f).

在JavaScript中我们有[] === []; // false,因为所有对象都通过引用进行了相等的测试,你可以在这里看到规范(7)和这里(1.f)。

You could write a function to do the test you want using Array.prototype.every

您可以编写一个函数来使用Array.prototype.every进行所需的测试

function equivArray(a, b) {
    return a.length === b.length && a.every(function (e, i) {return e === b[i];});
}

Now

现在

var foo = ['a', 'b', 1, 2],
    bar = ['a', 'b', 1, 2];

equivArray(foo, bar); // true

#5


1  

This is how javascript equal (==) operator works:

这是javascript equal(==)运算符的工作原理:

两个相等数组的比较失败

and here how the strict equal works (===):

在这里严格的平等工作如何(===):

两个相等数组的比较失败

Images from JavaScript Equality Table.

来自JavaScript Equality Table的图片。

#1


2  

Arrays in ECMAscript are also just a specialised form of Object. That in turn means, if you compare array1 with array2 using == or === you're comparing effectively two object references, not the array itself nor their contents.

ECMAscript中的数组也只是Object的一种特殊形式。这反过来意味着,如果你使用==或===比较array1和array2,你有效地比较了两个对象引用,而不是数组本身及其内容。

Actually, your second approach by joining the arrays and compare that outcome is not bad, if you can guarantee that the contents are always strings. Otherwise you would have to loop the array, compare each value individually and of course also compare the .length of those arrays.

实际上,如果可以保证内容始终是字符串,那么加入数组并比较结果的第二种方法也不错。否则你必须循环数组,单独比较每个值,当然还要比较这些数组的.length。

#2


2  

JavaScript object comparisons (including comparisons between array objects) merely compare the reference values. Two different objects are never equal to each other, no matter what they look like.

JavaScript对象比较(包括数组对象之间的比较)仅比较参考值。两个不同的对象永远不会彼此相等,无论它们看起来如何。

You can of course write your own array comparison function based on your own criteria for what it means for one array to be equal to another. If the arrays should contain the same values in the same order to be considered equal, for example, then:

您当然可以根据自己的标准编写自己的数组比较函数,以确定一个数组与另一个数组相等。例如,如果数组应包含相同顺序的相同值以使其相等,则:

function arraysEq(a1, a2) {
  if (a1.length != a2.length) return false;
  for (var i = 0; i < a1.length; ++i)
    if (a1[i] !== a2[i]) return false;
  return true;
}

Note that that's just an example; it should not be considered a general solution to the "how do I compare two arrays" problem.

请注意,这只是一个例子;它不应该被认为是“如何比较两个数组”问题的一般解决方案。

#3


2  

The == operator in Javascript does not compare the contents of two arrays or objects. Instead, it just compares to see if the two arrays or objects are actually the same object. You can make your own comparison function if you want to see if the two contain the same contents. One possible way of doing that for arrays that contain strings would be with .join():

Javascript中的==运算符不会比较两个数组或对象的内容。相反,它只是比较两个数组或对象是否实际上是同一个对象。如果要查看两者是否包含相同的内容,可以创建自己的比较功能。对包含字符串的数组执行此操作的一种可能方法是使用.join():

colors.join("") === initial.join("")

This isn't entirely foolproof for all possible array contents, but if you know the array only contains strings and the strings won't contain commas themselves, then this works as a shortcut. A more robust content comparison can also be written. For a one level deep comparison of arrays, you can use this:

对于所有可能的数组内容,这并非完全万无一失,但是如果您知道数组只包含字符串并且字符串本身不包含逗号,那么这将作为快捷方式。还可以编写更强大的内容比较。对于数组的一级深度比较,您可以使用:

function compareArrays(a, b) {
    if (typeof a.length === "number" && a.length === b.length) {
        for (var i = 0; i < a.length; i++) {
            if (a[i] !== b[i]) {
                return false;
            }
        }
        return true;
    }
    return false;
}

For a deep comparison where each array could contain other arrays or objects that you also want to compare the contents of those, then you'd need a recursive solution that could deep compare both object properties and array elements.

对于每个数组可能包含其他数组或对象的深度比较,您还需要比较其中的内容,那么您需要一个可以深入比较对象属性和数组元素的递归解决方案。

You can do a deep comparison of both objects and arrays with something like this:

您可以使用以下内容对对象和数组进行深入比较:

function compareObjects(a, b) {
    // if both are objects, then do a deep comparison of all properties
    if (typeof a === "object" && typeof b === "object") {
        var aKeys = Object.keys(a).sort(), bKeys = Object.keys(b).sort();
        var prop;
        if (!compareArrays(aKeys, bKeys)) {
            return false;
        }
        // here we know the two objects have the same keys, check values now
        for (var i = 0; i < aKeys.length; i++) {
            prop = aKeys[i];
            if (typeof a[prop] === "object" && typeof b[prop] === "object") {
                if (!compareObjects(a[prop], b[prop])) {
                    return false;
                }
            } else if (a[prop] !== b[prop]) {
                return false;
            }
        }
        return true;
    } else {
        // not both objects so just do straight equality
        return a === b;
    }
}

function compareArrays(a, b) {
    if (typeof a.length === "number" && a.length === b.length) {
        for (var i = 0; i < a.length; i++) {
            if (a[i] !== b[i]) {
                return false;
            }
        }
        return true;
    }
    return false;
}

This would allow you to compare nested structures that have objects inside of them and to compare plain objects in addition to arrays like this:

这将允许您比较在其中包含对象的嵌套结构,并比较除了这样的数组之外的普通对象:

var a = {foo: [1,2,3,["a","b","c"]], fee: {a: "1"}};
var b = {fee: {a: "1"}, foo: [1,2,3,4,["a","b","c"]]};

Note: This compares publicly enumerable properties of objects or arrays. It does not compare private (e.g. closure) variables of a custom formed object (say a constructor that creates a closure). For those, the only way to compare those is with a custom comparison method that can access the private data of the objects themselves.

注意:这会比较对象或数组的公开可枚举属性。它不比较自定义形成对象的私有(例如闭包)变量(比如创建闭包的构造函数)。对于那些,比较它们的唯一方法是使用自定义比较方法,该方法可以访问对象本身的私有数据。

Note: This does not work for objects or arrays that contain circular references (DOM objects are notorious for circular references). It is possible to make it work with circular references by keeping a track of all references that are already being compared in an array or Set and not recursing into them again if already in the process of comparing them.

注意:这不适用于包含循环引用的对象或数组(DOM对象因循环引用而臭名昭着)。通过跟踪已经在数组或集合中进行比较的所有引用,并且如果已经在比较它们的过程中再次递归它们,可以使它与循环引用一起工作。

#4


1  

In JavaScript we have [] === []; // false because all Objects are tested for equality by their reference, you can see the spec on this here (7) and here (1.f).

在JavaScript中我们有[] === []; // false,因为所有对象都通过引用进行了相等的测试,你可以在这里看到规范(7)和这里(1.f)。

You could write a function to do the test you want using Array.prototype.every

您可以编写一个函数来使用Array.prototype.every进行所需的测试

function equivArray(a, b) {
    return a.length === b.length && a.every(function (e, i) {return e === b[i];});
}

Now

现在

var foo = ['a', 'b', 1, 2],
    bar = ['a', 'b', 1, 2];

equivArray(foo, bar); // true

#5


1  

This is how javascript equal (==) operator works:

这是javascript equal(==)运算符的工作原理:

两个相等数组的比较失败

and here how the strict equal works (===):

在这里严格的平等工作如何(===):

两个相等数组的比较失败

Images from JavaScript Equality Table.

来自JavaScript Equality Table的图片。