这是有效的JavaScript数组比较算法吗?

时间:2013-07-11 22:55:38

标签: javascript arrays compare

原始主题,我知道,但任何人都可以评论以下算法来比较两个ES5 arrrays:

function equal_arrays(a, b) {
    "use strict";

    var c = 0;

    return a.every(function (e) {
        return e === b[c++];
    });
}

我认为这是非常干净且明显地使用[] .every()来快速比较两个数组? 我有那种唠叨“肯定不会那么简单吗?”感觉呢?

注意:当两个数组包含严格相同的相同位置的所有元素时,它们是相等的。因此,元素索引和元素值必须完全相等。不同类型的值被认为是不相等的。稀疏阵列也进行了比较。

测试案例:

      equal_arrays([],[]) ; // => true
      equal_arrays([1,2],[1,2]) ; // => true
      equal_arrays([1,,2],[1,,2]) ; // => true
      equal_arrays([,],[,]); // => true
      equal_arrays([1,,3,,,],[1,,3,,,]); // => true

使用案例yielding =>是的,人们可以想象自己。比较非数组是语法错误。

非常感谢良好的意义和有用的贡献者。似乎“最好的”(从来没有这样的事情)实现是这样的:

function has(element, index)
{
    return this[index] === element;
}

function equal_arrays(a, b)
{
    return (a.length === b.length) && a.every(has, b) && b.every(has, a);
}

@ tom的双向every()的实现,这是必要的sp,像这样的测试用例工作:

equal_arrays([1,,3],[1,2,3]); //=> false 

再次感谢...

4 个答案:

答案 0 :(得分:4)

不,它无效。来自MDN docs

  仅对已分配值的数组的索引调用

callback;对于已删除或从未分配过值的索引,不会调用它。

因此,如果第一个数组有“间隙”,则会跳过它们。

equal_arrays([1, 2, , 4], [1, 2, 4]); // true
equal_arrays([1, 2, 4], [1, 2, , 4]); // false

这是一个更好的实现:

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

这是@ RobG的双向every()想法的优雅实现:

function has(element, index)
{
    return this[index] === element;
}

function equal_arrays(a, b)
{
    return (a.length === b.length) && a.every(has, b) && b.every(has, a);
}

答案 1 :(得分:3)

  

我有那种唠叨“肯定不会那么简单吗?”感觉呢?

不,不是。在一个阵列上使用每个将为那个阵列的每个成员测试它,而不是另一个。你必须测试两种方式。

此外,这取决于您的“平等”标准。您可能希望同一索引的每个成员具有相同的值,但您可能不关心顺序,因此[1,2]等于[2,1]?并且[,,,2]等于[2]

此外,[1,,2]应该等于[1,undefined,2],即不存在的成员是否应该与具有undefined值的成员“相等”?

数组比较函数

以下可能会完成这项工作。它比较两种方式,检查自己的属性和值。我认为它涵盖了所有情况,但我愿意相信。作为一个单独的函数可能会更好,但添加到Array.prototype很方便。

// Test that own properties of two arrays have the same values
Array.prototype.isEqualTo = function(a) {
  var visited = {};
  if (this.length != a.length) return false;

  // Test every own property of this, remember tested properties
  for (var p in this) {

    if (this.hasOwnProperty(p)) {
      visited[p] = p;

      if (!(a.hasOwnProperty(p)) || this[p] !== a[p]) {
        return false; 
      }
    }
  }

  // Reverse test that comparison array only has tested properties
  for (var q in a) {
    if (a.hasOwnProperty(q) && !(q in this)) {
      return false;
    }
  }
  return true;
}

console.log([1,,2].isEqualTo([1,undefined,2])); // false, not defined != undefined
console.log([1,,2].isEqualTo([1,2]));           // false, different length
console.log([1,2].isEqualTo([1,2]));            // true

请注意,应该忽略继承的属性,就好像比较来自不同窗口的数组(例如,一个来自框架),然后继承的属性将不相等。

答案 2 :(得分:2)

作为替代方案,如果您只想检查两个阵列是否完全相同,您可以这样做:

var a = [1,2,3,4];
var b = [1,2,3,4];

JSON.stringify(a) == JSON.stringify(b); //= true

这应该适用于数字和字符串数组。

答案 3 :(得分:2)

正如CrazyTrain所说,增量值是无用的,你需要首先检查长度:

function equalArrays( a, b ) {
  "use strict";
  if (a.length !== b.length) return false;
  return a.filter(function(el){ return el;}).every(function(e, i) {
    return e === b[i];
  });
}

是一种有效的算法,可以按值比较数组。