如何比较javascript数组的内容,而不是它们的顺序?

kra*_*r65 5 javascript arrays comparison

正如标题所说,我想比较两个 js 数组,其中我只关心内容是否相同,但我不关心它们的顺序是否相同。所以我期望的是:

[1, 2, 3, 3] == [1, 2, 3, 3]     // True
[1, 2, 3, 3] == [1, 3, 2, 3]     // True
[1, 2, 3, 3] == [1, 2]           // False
[1, 2, 3, 3] == [1, 2, 3]        // False
[1, 2, 3, 3] == [1, 2, 3, 3, 3]  // False
[1, 2, 3, 3] == [1, "2, 3, 3"]      // False
Run Code Online (Sandbox Code Playgroud)

显然比较运算符不起作用。从这个 SO answer我得到了下面的 Array.prototype 方法,但不幸的是,它也会检查顺序是否相同。

那么有人知道如何检查两个 js 数组是否包含相同的元素,而不考虑元素的顺序吗?欢迎所有提示!

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;
}   
Run Code Online (Sandbox Code Playgroud)

Oma*_*ady 8

在比较之前对它们进行排序:

从下面的评论中,如果您希望 2 个 arrs 包含不同的原始类型,请添加此排序功能。

function s(x,y){
    var pre = ['string' , 'number' , 'bool']
    if(typeof x!== typeof y )return pre.indexOf(typeof y) - pre.indexOf(typeof x);

    if(x === y)return 0;
    else return (x > y)?1:-1;

}
var arr1 = [1, 2, 3, 3].sort(s);
var arr2 = [1, 3, 2, 3].sort(s);

arr1.equals(arr2);// true
Run Code Online (Sandbox Code Playgroud)

  • 排序并不总是有效。正如我在另一个答案中解释的那样,“[1, '1'].sort()”和“['1', 1].sort()”都会使数组保持原始顺序。这个特定的示例在您的示例中不是问题,因为“equals”实现使用松散比较,但这本身就意味着其他问题(请参阅我对该问题的评论)。事实上,只有在处理相同原始数据类型的值时,排序才真正有效。(考虑到OP对问题的描述,情况可能是这样) (2认同)

Fel*_*ing 5

这是一个适用于原始值的解决方案。它使用一个对象作为原始映射并计算每个值的出现次数。但是,它还考虑了每个值的数据类型。

它首先检查数组的长度,作为快捷方式:

function equals(a, b) {
    if (a.length !== b.length) {
        return false;
    }

    var seen = {};
    a.forEach(function(v) {
        var key = (typeof v) + v;
        if (!seen[key]) {
            seen[key] = 0;
        }
        seen[key] += 1;
    });

    return b.every(function(v) {
        var key = (typeof v) + v;
        if (seen[key]) {
            seen[key] -= 1;
            return true;
        }
        // not (anymore) in the map? Wrong count, we can stop here
    });
}
Run Code Online (Sandbox Code Playgroud)

  • 好消息是 ES 2015 引入了地图!现在类型检查和字符串化已经过时,可以使用类似的东西来代替: `constcompareOutOfOrder = (arr1, arr2) =&gt; { if(arr1.length !== arr2.length){ return false; } } const counts = new Map(); arr1.forEach((value) =&gt; counts.set(value, (counts.get(value) ?? 0) + 1)); arr2.forEach((value) =&gt; counts.set(value, (counts.get(value) ?? 0) - 1)); return Array.from(counts.values()).every((count) =&gt; count === 0); };`。我怀疑是否有可能利用“return”…`.every(`…`);`在这里直接倒数。 (3认同)