我想比较两个数组。。。理想地、有效地。没有什么稀奇古怪的,如果它们是相同的,那就是真的,如果不是,那就是假的。毫不奇怪,比较运算符似乎不起作用。

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对每个数组进行编码,但是否有一种更快或“更好”的方法来简单地比较数组而不必遍历每个值?


当前回答

易于理解的

type Values = number | string;

/** Not sorted array */
function compare<Values>(a1: Array<Values>, a2: Array<Values>): boolean {
    if (a1.length !== a2.length) {
        return false;
    }

    /** Unique values */
    const set1 = new Set<Values>(a1);
    const set2 = new Set<Values>(a2);
    if (set1.size !== set2.size) {
        return false;
    }

    return [...set1].every((value) => [...set2].includes(value));
}

compare([1, 2, 3], [1, 2, 3]);    // true
compare([1, 2, 3], [1, 3, 2]);    // true
compare([1, 1, 1], [1, 2, 3]);    // false
compare([1, 1, 2, 3], [1, 2, 3]); // false

/** Sorted arrays, faster method */
function compareSorted<Values>(a1: Array<Values>, a2: Array<Values>): boolean {
    if (a1.length !== a2.length) {
        return false;
    }

    /** Unique values */
    const set1 = new Set<Values>(a1);
    const set2 = new Set<Values>(a2);
    if (set1.size !== set2.size) {
        return false;
    }

    return [...set1].every((value, index) => value === [...set2][index]);
}

compareSorted([1, 2, 3], [1, 2, 3]);    // true
compareSorted([1, 2, 3], [1, 3, 2]);    // false
compareSorted([1, 1, 1], [1, 2, 3]);    // false
compareSorted([1, 1, 2, 3], [1, 2, 3]); // false

其他回答

尝试了深度平等,并且成功了

var eq = require('deep-equal');
eq({a: 1, b: 2, c: [3, 4]}, {c: [3, 4], a: 1, b: 2});

您可以简单地使用lodash库中的isEqual。它非常高效和干净。

import isEqual from "lodash/isEqual";

const isTwoArraysEqual = isEqual(array1, array2);

根据TomášZato的回答,我同意仅迭代数组是最快的。此外(就像其他人已经说过的那样),函数应该被称为equals/equal,而不是compare。考虑到这一点,我修改了该函数,以处理比较数组的相似性(即它们具有相同的元素,但没有顺序),以供个人使用,并认为我将把它放在这里让大家看到。

Array.prototype.equals = function (array, strict) {
    if (!array)
        return false;

    if (arguments.length == 1)
        strict = true;

    if (this.length != array.length)
        return false;

    for (var i = 0; i < this.length; i++) {
        if (this[i] instanceof Array && array[i] instanceof Array) {
            if (!this[i].equals(array[i], strict))
                return false;
        }
        else if (strict && this[i] != array[i]) {
            return false;
        }
        else if (!strict) {
            return this.sort().equals(array.sort(), true);
        }
    }
    return true;
}

此函数接受默认为true的strict附加参数。这个严格的参数定义数组是否需要在内容和这些内容的顺序上完全相等,或者仅仅包含相同的内容。

例子:

var arr1 = [1, 2, 3, 4];
var arr2 = [2, 1, 4, 3];  // Loosely equal to 1
var arr3 = [2, 2, 3, 4];  // Not equal to 1
var arr4 = [1, 2, 3, 4];  // Strictly equal to 1

arr1.equals(arr2);         // false
arr1.equals(arr2, false);  // true
arr1.equals(arr3);         // false
arr1.equals(arr3, false);  // false
arr1.equals(arr4);         // true
arr1.equals(arr4, false);  // true

我还编写了一个函数的快速jsfiddle,以及这个示例:http://jsfiddle.net/Roundaround/DLkxX/

这里有很多好答案。我通常是这样做的-

if ( arr1.length === arr2.length && arr1.every((a1) => arr2.includes(a1)) ) {
   // logic
}

every()只在所有元素都通过给定的camparison时返回true思维方式如果在任何迭代中遇到错误,它将终止并返回false。时间复杂度为O(n*m)。

虽然这个问题的最佳答案是正确和良好的,但提供的代码可能需要一些改进。

下面是我自己比较数组和对象的代码。代码简短而简单:

Array.prototype.equals = function(otherArray) {
  if (!otherArray || this.length != otherArray.length) return false;
  return this.reduce(function(equal, item, index) {
    var otherItem = otherArray[index];
    var itemType = typeof item, otherItemType = typeof otherItem;
    if (itemType !== otherItemType) return false;
    return equal && (itemType === "object" ? item.equals(otherItem) : item === otherItem);
  }, true);
};

if(!Object.prototype.keys) {
  Object.prototype.keys = function() {
    var a = [];
    for (var key in this) {
      if (this.hasOwnProperty(key)) a.push(key);
    }
    return a;
  }
  Object.defineProperty(Object.prototype, "keys", {enumerable: false});
}

Object.prototype.equals = function(otherObject) {
  if (!otherObject) return false;
  var object = this, objectKeys = object.keys();
  if (!objectKeys.equals(otherObject.keys())) return false;
  return objectKeys.reduce(function(equal, key) {
    var value = object[key], otherValue = otherObject[key];
    var valueType = typeof value, otherValueType = typeof otherValue;
    if (valueType !== otherValueType) return false;
    // this will call Array.prototype.equals for arrays and Object.prototype.equals for objects
    return equal && (valueType === "object" ? value.equals(otherValue) : value === otherValue);
  }, true);
}
Object.defineProperty(Object.prototype, "equals", {enumerable: false});

此代码支持嵌套在对象中的数组和嵌套在数组中的对象。

您可以在下面的repl中看到一整套测试并自己测试代码:https://repl.it/Esfz/3