[英]What is the best way, algorithm, method to difference large lists of data?
[英]best algorithm to reconcile 3 lists
我正在寻找一种方法来协调来自3个不同来源的元素。 我已将元素简化为只有一个键(字符串)和版本(长)。
这些列表是同时获得的(2个来自不同的数据库查询,1个来自另一个系统上的内存缓存)。
对于我的最终结果,我只关心所有3个来源中不是相同版本的元素。 所以我关心的结果将是一个键列表,每个系统中都有相应的版本。
Element1 | system1:v100 | system2:v100 | system3:v101 |
Element2 | system1:missing | system2:v200 | system3:v200 |
并且可以丢弃具有相同版本的元素。
我想到的实现这两种方法是
等待所有数据源完成检索,然后遍历每个列表以聚合具有密钥组合+所有3个版本的主列表(丢弃所有相同的项目)。
一旦检索完第一个列表,就将其放入并发集合(如字典(在.net 4.0中提供))中,并在可用时立即开始聚合剩余列表(并入集合)。
我的想法是第二种方法会更快一些,但可能不会太多。 在所有3个来源都存在之前,我真的不能做太多,所以从第二种方法中获得的并不多,并且引入了争用。
也许还有其他方法可以解决这个问题? 此外,由于版本是使用longs存储的,并且将有100个(可能是数百万)个元素,因此内存分配可能会受到关注(因为这些对象很短暂,所以可能不是一个大问题)
HashSet是一个选项,因为它具有Union和Intersect方法
要使用它,您必须覆盖Equals和GetHashCode。
良好(唯一)哈希是性能的关键。
如果版本全部是v然后是数字,则可以使用数字来构建缺少为0的哈希。
让Int32玩,所以如果版本是Int10或更少可以创建一个完美的哈希。
另一个选项是ConcurrentDictionary(没有并发的HashSet)并且所有三个都加入了它。
仍然需要重写Equals和GetHashCode。
我的直觉是三个HashSets然后Union会更快。
如果所有版本都是数字版本,并且您可以使用0表示缺失,则可以将其打包到UInt32或UInt64中,并将其直接放在HashSet中。 联盟然后打开包装。 使用位推<<而不是数学来打包解包。
这只是两个UInt16但它在2秒内运行。
这比Hashing类要快。
如果所有三个版本都很长,那么HashSet <integral type>
将不是一个选项。
long1 ^ long2 ^ long3; 可能是一个很好的哈希,但这不是我的专业知识。
我知道元组上的GetHashCode很糟糕。
class Program
{
static void Main(string[] args)
{
HashSetComposite hsc1 = new HashSetComposite();
HashSetComposite hsc2 = new HashSetComposite();
for (UInt16 i = 0; i < 100; i++)
{
for (UInt16 j = 0; j < 40000; j++)
{
hsc1.Add(i, j);
}
for (UInt16 j = 20000; j < 60000; j++)
{
hsc2.Add(i, j);
}
}
Console.WriteLine(hsc1.Intersect(hsc2).Count().ToString());
Console.WriteLine(hsc1.Union(hsc2).Count().ToString());
}
}
public class HashSetComposite : HashSet<UInt32>
{
public void Add(UInt16 u1, UInt16 u2)
{
UInt32 unsignedKey = (((UInt32)u1) << 16) | u2;
Add(unsignedKey);
}
//left over notes from long
//ulong unsignedKey = (long) key;
//uint lowBits = (uint) (unsignedKey & 0xffffffffUL);
//uint highBits = (uint) (unsignedKey >> 32);
//int i1 = (int) highBits;
//int i2 = (int) lowBits;
}
使用ConcurrentDictionary测试,上面的速度提高了两倍。
锁上插件是很昂贵的。
您的问题似乎适合基于事件的解决方案。 基本上为每个来源分配事件以完成数据。 使用类型保持全局并发哈希。 在您的事件处理程序中查看已完成的数据源,如果您的并发哈希包含当前元素的键,则只需将其添加到列表中(如果不是仅插入具有给定元素的新列表)。
但是,根据您的性能要求,这可能会使您的应用程序过于复杂。 您的第一种方法是最简单的方法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.