【问题标题】:Efficient and async way to check if at least one element of an array is also an element of another array检查数组的至少一个元素是否也是另一个数组的元素的高效异步方法
【发布时间】:2013-12-27 16:17:16
【问题描述】:

我想确定一个数组是否至少有一个元素也包含在另一个数组中。

即时:

arr0 = [0]
arr1 = [1,2,3]
arr2 = [2,3,4]
arr3 = [1,5,3]

arrCompare(arr0, arr1) // false
arrCompare(arr1, arr2) // true
arrCompare(arr1, arr3) // true

到目前为止,我有:

array_has_one_common_element =        (a, b) ->
  breakLoop1 = false

  for num1 in a
    for num2 in b
      if num2 is num1
        breakLoop1 = true; break
    break if breakLoop1

  return breakLoop1

因为这个函数将在服务器端与 nodejs 一起使用,并且可能必须处理大数组,所以我想知道如何将它重写为异步(使用 async 库)。或者它是否足够高效?

【问题讨论】:

  • 是否可以将数组转换为 HashSet(映射)并相交?如果交集为空 - 数组没有共同项,否则交集是共同项。当交集为 O(n) 时,组合循环为 O(n^2)

标签: arrays node.js asynchronous coffeescript


【解决方案1】:

数组交集是一个非常慢的操作。因此,如果您使用大型数组,那么最好使用哈希集。

这是我使用哈希集的交集实现:

hashset = (elements) ->
  return elements unless Array.isArray elements
  set = {}
  set[e] = true for e in elements
  set

intersect = (a, b) ->
  s1 = hashset a
  s2 = hashset b
  s3 = {}
  for k of s1
    s3[k] = true if s2[k]
  s3

arrCompare = (a, b) ->
  Object.keys(intersect a, b).length isnt 0

我认为您实际上并不需要它是异步的。如果您不希望数组操作阻塞主线程 - 将它们分派给另一个进程(工作者)。

更新

以下是benchmark.js 的一些基准测试:

arr1 = [1..9999];
arr2 = [9999..99999];

{ name: 'My Code',
  mean: 0.004182571958225297 }
{ name: 'Your Code',
  mean: 2.1228081478333336 }
{ name: 'askkirati\'s Synchronous Code',
  mean: 3.569238156 }

两个字符串数组的相同基准:

arr1 = (Math.random().toString(36).slice(2,12) for i in [1..9999])
arr2 = (Math.random().toString(36).slice(2,12) for i in [1..9999])

{ name: 'My Code',
  mean: 0.009257149728395064 }
{ name: 'Your Code',
  mean: 1.5913590743333332 }
{ name: 'askkirati\'s Synchronous Code',
  mean: 1.418200398 }

我也尝试了两个非常大的数组,但我放弃了等待所有方法完成:

arr1 = [1..999999]
arr2 = [999999..9999999]

{ name: 'My Code',
  mean: 1.6512419735000001 }

如您所见,hashmap 交集的工作速度比循环交集快得多。而且在我的电脑上只需要 1.6 秒就可以相交两个 999999 元素数组。

【讨论】:

    【解决方案2】:

    这是使用 async.some 的一种方式

    var async = require('async');
    var arr0 = [0];
    var arr1 = [1,2,3];
    var arr2 = [2,3,4];
    var arr3 = [1,5,3];
    
    function testExist(arrayToCheck, arrayInCheck, mainCallback){
      async.some(arrayToCheck, function(item, callback){
        if(arrayInCheck.indexOf(item) != -1){
          callback(true);
        }
        else{
          callback(false);
        }
      }, function(result){
        mainCallback(result);
      });
    }
    testExist(arr0, arr1, function(result){
      console.log(result);
    });
    testExist(arr1, arr2, function(result){
      console.log(result);
    });
    
    testExist(arr2, arr3, function(result){
      console.log(result);
    });
    

    这里是不使用异步库的例子,Node.js 支持 array.some

    var arr0 = [0];
    var arr1 = [1,2,3];
    var arr2 = [2,3,4];
    var arr3 = [1,5,3];
    
    function testWithoutAsyncLibExist(arrayToCheck, arrayInCheck, callback){
      var check = arrayToCheck.some(function(el, index, array){
        return (arrayInCheck.indexOf(el) != -1);
      });
      callback(check);
    }
    testWithoutAsyncLibExist(arr0, arr1, function(result){
      console.log(result);
    });
    testWithoutAsyncLibExist(arr1, arr2, function(result){
      console.log(result);
    });
    testWithoutAsyncLibExist(arr2, arr3, function(result){
      console.log(result);
    });
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-07-28
      • 1970-01-01
      • 2021-01-30
      • 2020-06-13
      • 1970-01-01
      • 2022-01-02
      • 1970-01-01
      相关资源
      最近更新 更多