如何在JavaScript中比较数组? [英] How to compare arrays in JavaScript?

查看:119
本文介绍了如何在JavaScript中比较数组?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想比较两个数组......理想情况下,有效的。没有什么特别的,只是真正如果他们是相同的,而如果不是。毫不奇怪,比较操作似乎并没有工作。

I'd like to compare two arrays... ideally, efficiently. Nothing fancy, just true if they are identical, and false if not. Not surprisingly, the comparison operator doesn't seem to work.

var a1 = [1,2,3];
var a2 = [1,2,3];
console.log(a1==a2);    // Returns false
console.log(JSON.stringify(a1)==JSON.stringify(a2));    // Returns true

编码每个数组JSON做,但有一个更快或更好的方式来简单地比较阵列,无需通过每个值迭代?

JSON encoding each array does, but is there a faster or "better" way to simply compare arrays without having to iterate through each value?

推荐答案

我真的不能相信,很多人想的阵列比较字符串。所以,虽然这是老问题,我会添加在右侧办法比较阵列 - 通过他们循环和比较每个值:

I can't really believe that so many people want to compare arrays as strings. So, though this is old question, I will add the right way to compare arrays - loop through them and compare every value:

// Warn if overriding existing method
if(Array.prototype.equals)
    console.warn("Overriding existing Array.prototype.equals. Possible causes: New API defines the method, there's a framework conflict or you've got double inclusions in your code.");
// attach the .equals method to Array's prototype to call it on any array
Array.prototype.equals = function (array) {
    // if the other array is a falsy value, return
    if (!array)
        return false;

    // compare lengths - can save a lot of time 
    if (this.length != array.length)
        return false;

    for (var i = 0, l=this.length; i < l; i++) {
        // Check if we have nested arrays
        if (this[i] instanceof Array && array[i] instanceof Array) {
            // recurse into the nested arrays
            if (!this[i].equals(array[i]))
                return false;       
        }           
        else if (this[i] != array[i]) { 
            // Warning - two different object instances will never be equal: {x:20} != {x:20}
            return false;   
        }           
    }       
    return true;
}
// Hide method from for-in loops
Object.defineProperty(Array.prototype, "equals", {enumerable: false});

用法:

[1, 2, [3, 4]].equals([1, 2, [3, 2]]) === false;
[1, "2,3"].equals([1, 2, 3]) === false;
[1, 2, [3, 4]].equals([1, 2, [3, 4]]) === true;
[1, 2, 1, 2].equals([1, 2, 1, 2]) === true;

您可能会说的但它的速度要快得多比较字符串 - 没有循环... 的好,那你要注意有循环。首先递归循环数组转换为字符串;第二,比较两个字符串。所以这种方法的是不是使用字符串快

You may say "But it is much faster to compare strings - no loops..." well, then you should note there ARE loops. First recursive loop that converts Array to string and second, that compares two strings. So this method is faster than use of string.

<子>相信大量数据应该总是存储在阵列中,不中的对象。但是如果使用的对象,它们可以部分相比过。结果,
方法如下:

我上文所述,这两个目标的实例永远不会相等,即使它们包含相同的数据的时刻:

I've stated above, that two object instances will never be equal, even if they contain same data at the moment:

({a:1, foo:"bar", numberOfTheBeast: 666}) == ({a:1, foo:"bar", numberOfTheBeast: 666})  //false

这是有原因的,因为可能会出现,例如私有变量。

This has a reason, since there may be, for example private variables within objects.

不过,如果你只是用对象的结构包含数据,比较仍然是可能的:

However, if you just use object structure to contain data, comparing is still possible:

Object.prototype.equals = function(object2) {
    //For the first loop, we only check for types
    for (propName in this) {
        //Check for inherited methods and properties - like .equals itself
        //https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwnProperty
        //Return false if the return value is different
        if (this.hasOwnProperty(propName) != object2.hasOwnProperty(propName)) {
            return false;
        }
        //Check instance type
        else if (typeof this[propName] != typeof object2[propName]) {
            //Different types => not equal
            return false;
        }
    }
    //Now a deeper check using other objects property names
    for(propName in object2) {
        //We must check instances anyway, there may be a property that only exists in object2
            //I wonder, if remembering the checked values from the first loop would be faster or not 
        if (this.hasOwnProperty(propName) != object2.hasOwnProperty(propName)) {
            return false;
        }
        else if (typeof this[propName] != typeof object2[propName]) {
            return false;
        }
        //If the property is inherited, do not check any more (it must be equa if both objects inherit it)
        if(!this.hasOwnProperty(propName))
          continue;

        //Now the detail check and recursion

        //This returns the script back to the array comparing
        /**REQUIRES Array.equals**/
        if (this[propName] instanceof Array && object2[propName] instanceof Array) {
                   // recurse into the nested arrays
           if (!this[propName].equals(object2[propName]))
                        return false;
        }
        else if (this[propName] instanceof Object && object2[propName] instanceof Object) {
                   // recurse into another objects
                   //console.log("Recursing to compare ", this[propName],"with",object2[propName], " both named \""+propName+"\"");
           if (!this[propName].equals(object2[propName]))
                        return false;
        }
        //Normal value comparison for strings and numbers
        else if(this[propName] != object2[propName]) {
           return false;
        }
    }
    //If everything passed, let's say YES
    return true;
}  

但是,请记住,这个人是在这样的数据,而不是类实例和其他的东西比较JSON服务。如果你想比较铁道部复杂的对象,看看这个答案,它的超长功能。结果
为了与 Array.equals 这个工作你必须编辑原始功能一点点:

However, remember that this one is to serve in comparing JSON like data, not class instances and other stuff. If you want to compare mor complicated objects, look at this answer and it's superlong function.
To make this work with Array.equals you must edit the original function a little bit:

...
    // Check if we have nested arrays
    if (this[i] instanceof Array && array[i] instanceof Array) {
        // recurse into the nested arrays
        if (!this[i].equals(array[i]))
            return false;
    }
    /**REQUIRES OBJECT COMPARE**/
    else if (this[i] instanceof Object && array[i] instanceof Object) {
        // recurse into another objects
        //console.log("Recursing to compare ", this[propName],"with",object2[propName], " both named \""+propName+"\"");
        if (!this[i].equals(array[i]))
            return false;
        }
    else if (this[i] != array[i]) {
...

我这两个功能的做了一个小测试工具。

I made a little test tool for both of the functions.

<一个href=\"http://stackoverflow.com/questions/7837456/how-to-compare-arrays-in-javascript/14853974?noredirect=1#comment59337127_14853974\">Samy谢里夫已prepared 有用的功能,你正在寻找在嵌套的数组,这些都可以在这里的特定对象的情况:<一href=\"https://jsfiddle.net/SamyBencherif/8352y6yw/\">https://jsfiddle.net/SamyBencherif/8352y6yw/

Samy Bencherif has prepared useful functions for the case you're searching for a specific object in nested arrays, which are available here: https://jsfiddle.net/SamyBencherif/8352y6yw/

这篇关于如何在JavaScript中比较数组?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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