我有数十亿数据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";
}
答案 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分析看起来还不错,如果你想要更快地理解为什么它的速度要快得多。