我正在尝试设计一种算法,用于在多个工作表中查找Excel文件中的重复行。
假设以下内容:
1)文件可能非常大。考虑一个包含10个工作表(每个包含1,048,576行)并说30列数据的文件
2)重复的行可能不在同一工作表上。例如,Sheet1 / Row20可能是Sheet5 / Row123456
的副本3)确定一行是否与另一行重复,其中一列或多列可用作用户指定的条件(并非总是所有列必须相同,用户可以例如指定一个复制是当列2,3和5相同时)
4)无法更改基础数据的顺序(不先对数据进行排序,然后再检查相邻的行)。
5)算法必须具有内存效率。在Dictionary中存储行的所有列的所有值将占用太多内存。并非所有数据都可以同时存储在内存中(读入.NET multidim数组),因为它会将内存使用量加倍,因为它已经存储在Excel中。
6)算法必须使用Excel对象模型最小化IO。从Excel连续检索单行数据(或执行一些其他内置的Excel互操作)可能会很慢。
到目前为止,我对算法有两种不同的想法:
算法1)
a)创建一个字典< int,List<元组< int,int> >其中字典键是特定行中列中所需值的哈希值,列表<元组< int,int> >是计算到该哈希码
的工作表索引/行索引的列表b)一次从Excel中读取大量数据(比如50,000行)并填写字典。
c)在列表中找到列表具有计数的所有条目> 1然后遍历所有行并通过再次从Excel读取数据并比较这次的实际值来检查是否存在实际重复
算法2)
与算法1类似,但使用两个(或者三个)不同且独立的散列函数来创建元组< int,int>或者元组< int,int,int>作为词典的关键。如果散列函数是独立的,则除非行实际上相等,否则在特定键处存在碰撞的概率几乎为0%。因此,步骤1c)可以省略。
要获得algo1中使用的hashkey,我会做这样的事情:
private int GetHashKey(List<object> columns)
{
int hash = 23;
foreach (var o in columns)
hash = hash * 31 + o.GetHashCode();
return hash;
}
如果我想做算法2)我需要为对象定义一个扩展方法GetHashCode2()(或者至少是Range.Value2的可能的返回数据类型,它们是string,double,bool和int)
有人能想到更好的解决方案吗? 人们对Algo1与Algo2的看法是什么? 如果人们认为Algo2更好,任何想法我如何编码创建一个高效且健壮的GetHashCode2()函数并生成与GetHashCode()不同的哈希码?