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

is this valid JavaScript arrays comparing algorithm?

本文关键字:数组 比较 算法 JavaScript 有效      更新时间:2023-09-26

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

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

用例产生=>错误,可以想象她自己。比较非数组是一个语法错误。

非常感谢善意和乐于助人的贡献者。看起来"最好的"(从来没有这样的事情(实现是这样的:

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 

再次感谢...

不,它无效。来自 MDN 文档:

仅对已分配值的数组索引调用 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,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
请注意,应忽略继承的属性,

就像比较来自不同窗口的数组(例如,一个来自框架(一样,则继承的属性将不相等。

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

var a = [1,2,3,4];
var b = [1,2,3,4];
JSON.stringify(a) == JSON.stringify(b); //= true

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

正如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];
  });
}

是按值比较数组的有效算法。