【问题标题】:How can I find matching values in two arrays? [duplicate]如何在两个数组中找到匹配的值? [复制]
【发布时间】:2012-09-08 03:43:08
【问题描述】:

我有两个数组,我希望能够比较这两个数组并只返回匹配的值。例如,两个数组都有值cat,所以这就是将返回的值。我还没有找到这样的东西。返回相似性的最佳方法是什么?

var array1 = ["cat", "sum","fun", "run"];
var array2 = ["bat", "cat","dog","sun", "hut", "gut"];

//if value in array1 is equal to value in array2 then return match: cat

【问题讨论】:

标签: javascript arrays


【解决方案1】:

你可以使用:

const intersection = array1.filter(element => array2.includes(element));

【讨论】:

  • 这看起来是最简单最简洁的答案。不知道为什么它没有被标记为正确的。
  • 那是因为不是所有的浏览器都支持它,除非你使用 polyfill:developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
  • 截至 2019 年 4 月下旬,只有 IE 不提供支持。
  • const intersection = array1.filter(element => array2.indexOf(element) !== -1); 没有 polyfill。
  • @Learner 来自 ES6,您可以使用 Set 过滤掉重复值并将其值分布在这样的数组中:const intersection = [...new Set(array1.filter(element => array2.includes(element)))];
【解决方案2】:

当然,我的方法是遍历第一个数组一次并检查第二个数组中每个值的索引。如果索引为> -1,则将push 放到返回的数组中。

​Array.prototype.diff = function(arr2) {
    var ret = [];
    for(var i in this) {   
        if(arr2.indexOf(this[i]) > -1){
            ret.push(this[i]);
        }
    }
    return ret;
};

​ 我的解决方案不像其他解决方案那样使用两个循环,因此它可能运行得更快一些。如果您想避免使用for..in,您可以先对两个数组进行排序以重新索引它们的所有值:

Array.prototype.diff = function(arr2) {
    var ret = [];
    this.sort();
    arr2.sort();
    for(var i = 0; i < this.length; i += 1) {
        if(arr2.indexOf(this[i]) > -1){
            ret.push(this[i]);
        }
    }
    return ret;
};

用法如下:

var array1 = ["cat", "sum","fun", "run", "hut"];
var array2 = ["bat", "cat","dog","sun", "hut", "gut"];

console.log(array1.diff(array2));

如果您在扩展 Array 原型时遇到问题/问题,您可以轻松地将其更改为函数。

var diff = function(arr, arr2) {

您可以将函数最初表示this 的任何地方更改为arr2

【讨论】:

  • .indexOf() 只是移动循环。该方法在内部循环遍历目标数组。 (developer.mozilla.org/en-US/docs/JavaScript/Reference/…)
  • .indexOf() 函数可能比在兼容性替代方案中循环遍历所有数组更快。
  • indexOf() 是否足够聪明,可以在排序后使用二进制搜索?否则,这是 O(N^2) ,因为由于 indexOf() 执行线性扫描,您实际上是在进行嵌套循环。即使没有这个问题,当您可以使用对象作为哈希表在线性时间内执行此操作时,为什么会产生线性排序成本?
  • 我还没有听说过任何 ECMASCript 引擎可以切换到对排序数组进行二分搜索。将是一个有趣的优化,包括在数组中携带一个“排序”标志,但我想知道是否有足够的调用。
  • 这有点晚了,但看起来最新的 Chrome 版本至少有更快的 indexOf:jsperf.com/jquery-inarray-vs-underscore-indexof/43
【解决方案3】:

我发现@jota3 的建议对我来说非常有效。

var intersections = array1.filter(e => array2.indexOf(e) !== -1);

希望这会有所帮助!

【讨论】:

  • 这意味着您使用的是 ES2016 之前的 javascript 版本,其中添加了 include()。 indexOf() 适用于任何版本。
【解决方案4】:

O(n*m) 相比,此函数在O(n log(n) + m log(m)) 中运行(如在其他带有循环/indexOf 的解决方案中所见),如果您要处理大量值,这可能很有用。

但是,因为"a" &gt; 1"a" &lt; 1 都不是,这仅适用于相同类型的元素。

function intersect_arrays(a, b) {
    var sorted_a = a.concat().sort();
    var sorted_b = b.concat().sort();
    var common = [];
    var a_i = 0;
    var b_i = 0;

    while (a_i < a.length
           && b_i < b.length)
    {
        if (sorted_a[a_i] === sorted_b[b_i]) {
            common.push(sorted_a[a_i]);
            a_i++;
            b_i++;
        }
        else if(sorted_a[a_i] < sorted_b[b_i]) {
            a_i++;
        }
        else {
            b_i++;
        }
    }
    return common;
}

例子:

var array1 = ["cat", "sum", "fun", "hut"], //modified for additional match
    array2 = ["bat", "cat", "dog", "sun", "hut", "gut"];
intersect_arrays(array1, array2);
>> ["cat", "hut"]

【讨论】:

  • 复杂度其实是O(nlogn + mlogm + n + m),计算的时候忘了考虑while循环。
  • @Partha n 被快速增长的n logn 所包含,同样适用于mm log n
【解决方案5】:

每次迭代第一个数组中的元素时,循环遍历第二个数组,然后检查匹配项。

var array1 = ["cat", "sum", "fun", "run"],
    array2 = ["bat", "cat", "dog", "sun", "hut", "gut"];

function getMatch(a, b) {
    var matches = [];

    for ( var i = 0; i < a.length; i++ ) {
        for ( var e = 0; e < b.length; e++ ) {
            if ( a[i] === b[e] ) matches.push( a[i] );
        }
    }
    return matches;
}

getMatch(array1, array2); // ["cat"]

【讨论】:

  • 这使用 数组 1 的长度 * 数组 2 的长度 循环数...在这种情况下为 24 个循环。
  • 糟糕。感谢您指出这一点:)
  • 没问题。它可以工作,但它非常不必要,并且可能需要永远运行。您可以查看我的答案,以获得更好的 1 循环解决方案
【解决方案6】:
var array1  = [1, 2, 3, 4, 5, 6];
var array2 = [1, 2, 3, 4, 5, 6, 7, 8, 9];
var array3 = array2.filter(function(obj) { 
    return array1.indexOf(obj) == -1; 
});

【讨论】:

  • @Mr. 1.0 请看看这个高效干净的代码。
  • 你可能想解释一下上面的代码。
  • 从第一行去掉“,”并添加“;”
  • 这个最容易理解
【解决方案7】:

你可以使用javascript函数.find() 正如它在 MDN 中所说的,它将返回 第一个值 为真。如果找到这样的元素, find 立即 返回该元素的值。否则,find 返回undefined

var array1 = ["cat", "sum", "fun", "run", "cat"];
var array2 = ["bat", "cat", "dog", "sun", "hut", "gut"];

found = array1.find((val, index) => {
  console.log('index', index) // Stops at 0
  return array2.includes(val)
})
console.log(found)

或者使用.filter(),它首先循环遍历每个元素,然后将结果返回给你。

var array1 = ["cat", "sum", "fun", "run", "cat"];
var array2 = ["bat", "cat", "dog", "sun", "hut", "gut"];

found = array1.filter((val, index) => {
  console.log('index', index) // Stops at array1.length - 1
  return array2.includes(val)
})
console.log(found)

【讨论】:

    【解决方案8】:

    使用 lodash

    GLOBAL.utils = require('lodash')
    var arr1 = ['first' , 'second'];
    var arr2 = ['second '];
    
    var result = utils.difference(arr1 , arr2);
    console.log ( "result :" + result );
    

    【讨论】:

      【解决方案9】:

      作为答案完成,以便我可以进行格式化...

      这是您需要经历的过程。循环遍历数组以获取详细信息。

      create an empty array
      loop through array1, element by element. {
        loop through array2, element by element {
          if array1.element == array2.element {
            add to your new array
          }
        }
      }
      

      【讨论】:

      • 这使用 数组 1 的长度 * 数组 2 的长度 循环数...在这种情况下为 24 个循环.. 最好只检查是否array1 中值的索引存在于 array2 中,然后只使用 1 个循环。看我的回答。
      • 我想过。 .indexOf() 仍然不是所有地方都支持,尽管它可以很容易地被猴子补丁...和.indexOf(),至少在 Mozilla 猴子补丁版本 (developer.mozilla.org/en-US/docs/JavaScript/Reference/…) 中仍然循环。它只是将其中一个循环移动到 indexOf 函数。
      • 各大浏览器都支持,看兼容性表...
      • 我很清楚 indexOf 支持和不支持的位置。我的主要 点是您的解决方案仍然是一个双循环解决方案。其中一个循环被隐藏了。
      • 是的——但我怀疑执行速度是这里想要的目标。这是一个“101 级”问题,因此 OP 需要一个最能描述整个过程的答案,而不需要捷径。 确切地了解正在发生的事情更重要。
      【解决方案10】:

      如果您的值是非空字符串或数字,则可以将对象用作字典:

      var map = {}, result = [], i;
      for (i = 0; i < array1.length; ++i) {
          map[array1[i]] = 1;
      }
      
      for (i = 0; i < array2.length; ++i) {
          if (map[array2[i]] === 1) {
              result.push(array2[i]);
      
              // avoid returning a value twice if it appears twice in array 2
              map[array2[i]] = 0;
          }
      }
      
      return result;
      

      【讨论】:

      • 使用 2 个循环。比其他解决方案更好,但您可以将其降低到 1
      【解决方案11】:

      像 underscore 和 lodash 这样的库有一个名为 intersection 的实用方法,可以在传入的数组中查找匹配项。看看:http://underscorejs.org/#intersection

      【讨论】:

      • 好点@EricLeschinski。我修改了答案。
      【解决方案12】:

      使用一些 ES6:

      let sortedArray = [];
      firstArr.map((first) => {
        sortedArray[defaultArray.findIndex(def => def === first)] = first;
      });
      sortedArray = sortedArray.filter(v => v);
      

      这个sn-p也根据defaultArray

      的顺序对firstArr进行排序

      喜欢:

      let firstArr = ['apple', 'kiwi', 'banana'];
      let defaultArray = ['kiwi', 'apple', 'pear'];
      ...
      console.log(sortedArray);
      // ['kiwi', 'apple'];
      

      【讨论】:

        【解决方案13】:

        迭代array1并找到array2中存在的indexof元素。

        var array1 = ["cat", "sum","fun", "run"];
        var array2 = ["bat", "cat","sun", "hut", "gut"];
        var str='';
        for(var i=0;i<array1.length;i++){
                if(array2.indexOf(array1[i]) != -1){
                   str+=array1[i]+' ';
               };
            }
        console.log(str)
        

        【讨论】:

        • 只有代码是没有意义的。解释你给 OP 的答案。
        猜你喜欢
        • 2012-12-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-05-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多