【问题标题】:Javascript: Compare three arraysJavascript:比较三个数组
【发布时间】:2011-12-03 08:59:17
【问题描述】:

我想比较许多数组并组合任何相同的数组:

A = [1,2,3];
B = [1,2,3];
C = [1,2,3];

D = [10,11,12];
E = [10,11,12];
F = [10,11,12];

G = [13,14];
H = [13,14];

如果有相同的数组,那么我想用相同的数组创建新的数组:

I = [1,2,3];
J = [10,11,12];
K = [13,14];

我是否需要针对其他数组中的所有元素遍历一个数组中的每个元素?

for (var i in A) {
    for (var j in B) {
        if (A[i] == J[j]) {
            // create new arrays
        }
    }
}

等等……

然后,从匹配项中创建新数组?听起来开销很大。

最好的方法是什么?

谢谢!

【问题讨论】:

  • for-in 迭代对象键。它不是 for-each 循环,您不应该在数组上使用它。
  • @missingno cmets 很棒,但请尝试解释为什么不应该使用某些东西或提供链接。谢谢。
  • 我应该更明确一点。除了索引属性(您真正关心的属性)之外,数组还有其他属性,并且 for-in 也可以遍历它们(除非您的浏览器一直在保护您免受这种影响)。如果你决定有一天使用一个改变 Array.prototype 的库,比如 MooTools 或 Prototype,那么这将是特别危险的,并且突然很多虚假的东西开始出现在你的循环中。要迭代烤箱数组,您应该使用普通的 for 循环或其中一种迭代方法,如 .forEach(如果您的浏览器/库支持)

标签: javascript arrays loops for-loop


【解决方案1】:

我相信是这样,但至少你可以使用一个比较数组函数来使它更容易,即使它同样慢:

function compareArrays(arr1,arr2)
{
    if (arr1.length != arr2.length) return false;
    for (var i = 0; i < arr2.length; i++) 
    {
        if (arr1[i].compareArrays) 
        { //likely nested arr2ay
            if (!arr1[i].compareArrays(arr2[i])) return false;
            else continue;
        }
        if (arr1[i] != arr2[i]) return false;
    }
    return true;
}

然后,您只需要在遍历数组时使用此函数即可。

【讨论】:

  • 我想指出我在其他地方得到了这个功能,可能是在 Stackoverflow 上,但我早就忘记了在哪里。
【解决方案2】:

根据您对相同的定义,您可以转换为字符串并进行比较。

if (A.toString() == B.toString()) { //combine }

【讨论】:

    【解决方案3】:

    嗯...我会这样做

    function combine(arr1, arr2)
    {
        if(arr1.join(',') === arr2.join(','))
            return arr1;
    }
    

    或者对于许多数组

    function combine(arrList)
    {
        var pass = true;
        var compareArray = arrList[0];
        for(var i in arrList)
            pass = pass && (arrList[i].join(',') === compareArray.join(','));
        if(pass)
            return compareArray;
    }
    
    arr = combine([[1,2,3],[1,2,3],[1,2,3]]); // results in [1,2,3]
    

    【讨论】:

    • @nrabinowitz 我看不出它与列出的任何其他方法有什么不同。即使在您的情况下,它也会循环与数组一样多。唯一的区别是您将它们存储在一个对象中。您的也有可能进行多重比较(哈希部分中的哈希),使其接触数组的次数超过现有数组的数量(例如,对于 5 个数组,它可能进行 8 次比较)。在那种情况下,如果我对其进行优化,我的只会进行 5 次比较,甚至 4 次。
    • 我只比较哈希,而不是数组。我的版本是 O(n) - 对于 5 个数组,它会进行 5 次哈希对象查找。也许我遗漏了一些关于你的版本的东西——我只是没有看到你的方法是如何获取一个数组列表并产生一个唯一数组列表的,我认为这是 OP 想要的。
    • 我不认为这个解决方案是正确的;它所做的只是检查第一个数组是否等于所有其他数组,如果相等,则返回第一个数组。
    • @Peter 这就是 OP 所要求的。目标是合并相同的数组。您可以将它们作为字符串进行比较,如果它们相同,则合并没有真正意义。您可以返回第一个。
    • @Joseph - 是的,但是如果你想要 all 的唯一数组(我认为 OP 会这样做),你需要在每个数组中运行它序列,与其他所有数组进行比较。
    【解决方案4】:

    如果您只是想完成唯一数组,我会使用哈希方法:

    var myArrays = [A,B,C,D,E,F,G],
        uniques = [],
        hashes = {};
    
    for (var i=0; i < myArrays.length; i++) {
        var hash = JSON.stringify(myArrays[i]); // or .toString(), or whatever
        if (!(hash in hashes)) {
            hashes[hash] = true;
            uniques.push(myArrays[i]);
        }
    }
    // uniques now holds all unique arrays
    

    【讨论】:

    • 除了一种情况外,仍然存在一些问题。疯了,我知道,但就是这样。能否提供一个运行良好的 jsFiddle 示例?
    • 给你:jsfiddle.net/nrabinowitz/L4Ekx/1。我的for 循环中有错字-var i; 应该是var i=0;。上面更正了。
    • 经过各种测试,我只能说这个效果非常好!为了使 JSON.stringify 能够与旧版浏览器一起使用,我只需要添加 Douglas Crockford 的 JSON-js mini-lib。我调用了 json2.js 文件,一切正常,尤其是在 IE 6/7 中:github.com/douglascrockford/JSON-js
    • 如果我可以为您的回答加分,我会的!谢谢你:)
    • 很高兴这对你有用! JSON.stringify 可能是这里可用的最佳哈希函数,但如果您知道您的数组只能保存数字或字符串,您可能可以使用简单的 .toString()
    【解决方案5】:

    如果你只是比较原始数组——数字或字符串,比如说——你可以比较它们的字符串表示。

    function simpleArrayMatch(A,B){
        return String{A)===String(B);
    }
    

    【讨论】:

    • 我很好奇这个功能。你能把它再冲洗一下,这样我就可以看到它的工作环境了吗?
    • 没有 jsFiddle 示例?适用于一组数组,但多个数组呢?
    【解决方案6】:

    假设每个数组中只有数字或文本,所以这可能是一种可行的方法,无需遍历任何数组:

    (见小提琴here

    代码:

    A = [1,2,3];
    B = [1,2,3];
    C = [1,2,3];
    
    D = [10,11,12];
    E = [10,11,12];
    F = [10,11,12];
    
    G = [13,14];
    H = [13,14];
    
    function compareArr(arrList){
        var S = '@' + arrList.join('@');
        var re = /(@[^@]+)(@.*)?(\1)(@|$)/gi
        var afterReplace=''; var i=0;
        while(afterReplace!=S && i<100){
            afterReplace=S;
            S = S.replace( re, "$1$2$4" )
            i++
        }
    
        return S.substr(1,S.length-1).replace(/@/g,'<br>')
    }
    
    $('html').append( compareArr([A,B,C,D,E,F,G,H]) )
    

    策略是将所有数组连接成一个字符串,以“@”作为分隔符。然后使用正则表达式替换字符串中所有重复的部分,最后拆分字符串,然后你就有了列表唯一数组。

    在我的代码中使用 while 循环的原因只是因为我无法编写更好的正则表达式模式来一次删除重复的片段。正在寻找更好的正则表达式?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-04-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-09
      • 2013-05-02
      相关资源
      最近更新 更多