如何快速标记数据

时间:2016-07-15 12:09:03

标签: javascript arrays algorithm quicksort

我有数十亿数据A和数十亿数据B

如果B中的A项,则标记项目“红色”,如果不是,则将其标记为“蓝色”

我可以想出一个非常缓慢的功能:

var A=[10000000]
,B=[1000000];
for (var m = 0; m < A.length; m++) {
              
  var isInB = false;
  for (var n = 0; n < B.length; n++) {
    if (B[n].id ==A[m].id) {
      isInB = true;
      break;
    }
  }
  
  A[m].color=isInB?"red":"blue";
               
}

2 个答案:

答案 0 :(得分:2)

您可以使用临时集,然后对其执行测试。以下是ES6的实现:

// sample data: primes (A) and Fibonacci numbers (B)
var A = [{id: 1}, {id: 2}, {id: 3}, {id: 5}, {id: 7}, {id: 11}, {id: 13}, {id: 17},
         {id: 19}, {id: 23}];
var B = [{id: 1}, {id: 2}, {id: 3}, {id: 5}, {id: 8}, {id: 13}, {id: 21}, {id: 34}];

// Create a set with all ID values that exist in B:
var bSet = new Set(B.map(b => b.id));
// Enrich A with color property based on that set:
A.forEach(a => a.color = bSet.has(a.id) ? 'red' : 'blue');

console.log(A);

由于这是基于一个集合,因此无需先对数据进行排序。

性能

在比较算法时,我将忽略创建color属性所花费的时间,因为两种算法都必须对A的所有元素执行此操作。

原始算法的时间复杂度为 O(nm),其中 n m 是A和B中元素的数量分别

与原始算法相比,使用此集可以提高性能。许多JavaScript引擎实现具有接近常量插入和查找时间的集合(使用哈希,例如参见V8),但如果使用标准搜索树,它可能是 O(logn),< em> n 是集合中元素的数量。我将采取最坏的情况并假设 O(logn)进行两种操作。

上述算法将在 O(m.logm)时创建集合,然后使用 O(n.logm)时间中的额外属性填充A.

这使得总时间复杂度 O((n + m)logm),这比 O(n.m)更好。如果常量插入和查找时间适用,则会减少为简单的 O(n + m)时间复杂度。

答案 1 :(得分:0)

我认为@trincot的答案是正确的,但我认为我会提供自己的思考过程来解决它。

如果我们仔细研究一下您的问题陈述,我认为存在一个好的算法:

  

如果B中的A项,则标记项目“红色”,如果不是,则将其标记为“蓝色”

在伪代码中,这变为:

for(item in b):
  if(a.contains(item)){
    b.markRed();
  }else{
    b.markBlue();
  }
}

这有一个循环而不是两个循环,这意味着我们回到O(n)领域而不是非常糟糕的O(n ^ 2)。那么问题就变成了,我们为A使用了什么数据结构,以便有一个“包含”方法? @trincot建议使用Set,但任何地图/字典实现也可以满足它的目的。

创建set / map / dictionary会产生额外的成本,但它比嵌套循环要少得多。

所以,它更快,因为我们用一个恒定时间查找替换了一个循环,这意味着对于每个B,我们正在进行1次操作而不是A次操作。

@ trincot的big-O分析看起来还不错,如果你想要更快地理解为什么它的速度要快得多。