Algorithm 使用什么算法删除重复项?

Algorithm 使用什么算法删除重复项?,algorithm,duplicates,Algorithm,Duplicates,假设我们有一个文件,例如称为“A.txt”。我们知道有一些重复的元素。“A.txt”非常大,比内存大十倍多,可能在50GB左右。有时,B的大小大约等于A的大小,有时比A的大小小很多倍。 让它有这样的结构: a 1 b 2 c 445 a 1 我们需要得到文件“B.txt”,它不会有这样的副本。例如,它应该是这样的: a 1 b 2 c 445 我考虑了复制A和B的算法,然后取B中的第一个字符串,互相查找,如果找到相同的字符串,则删除重复的字符串。然后取第二个字符串,等等 但我认为它太慢了。我

假设我们有一个文件,例如称为“A.txt”。我们知道有一些重复的元素。“A.txt”非常大,比内存大十倍多,可能在50GB左右。有时,B的大小大约等于A的大小,有时比A的大小小很多倍。 让它有这样的结构:

a 1
b 2
c 445
a 1
我们需要得到文件“B.txt”,它不会有这样的副本。例如,它应该是这样的:

a 1
b 2
c 445
我考虑了复制A和B的算法,然后取B中的第一个字符串,互相查找,如果找到相同的字符串,则删除重复的字符串。然后取第二个字符串,等等

但我认为它太慢了。我能用什么

A是不是数据库!请不要用SQL

对不起,那没有说,分类是可以的


虽然可以排序,但是如果不能排序呢?

你基本上必须建立一个可搜索的结果集(如果语言让你想起数据库技术,这不是偶然的,不管你多么讨厌数据库处理与你相同的问题)

其中一种可能的有效数据结构是排序范围(可实现为某种类型的树)或哈希表。因此,在处理文件时,您可以高效地将每个记录插入结果集中,并在该阶段检查结果是否已经存在。完成后,将减少一组唯一记录

结果集也可以存储对任何原始记录的某种引用,而不是复制实际记录。这取决于记录是否足够大,以使其成为更有效的解决方案

或者,您可以简单地在原始数据中添加一个标记,无论是否包含该记录


(也考虑使用一个有效的存储格式,如NETCDF二进制数据,因为文本表示的访问和处理要慢得多)。一个解决方案是对文件进行排序,然后一行一行复制到一个新文件中,过滤出连续的重复。 然后问题变成了:如何对太大而无法放入内存的文件进行排序

给你


另请参见。

假设您可以将文件的
1/k
部分放入内存,并且仍然有空间用于工作数据结构。整个文件可以在
k
或更少的过程中处理,如下所示,这可能比根据行长度和排序算法常数对整个文件进行排序快得多。排序平均值
O(n ln)
下面的过程是
O(kn)
最坏情况。例如,如果行的平均长度为10个字符,并且有n=5G行,
ln(n)~22.3
。此外,如果您的输出文件
B
比输入文件
A
小得多,则该过程可能只需要一到两次

过程:

  • 为输入缓冲区I分配数兆字节,为结果缓冲区R分配数千兆字节,为哈希表H分配约千兆字节。打开输入文件F和输出文件O
  • 重复:通过步骤3从F中填充I并将其处理为R
  • 对于I中的每一行L,检查L是否已经在H和R中。如果已经在H和R中,则转到下一行L,否则将L添加到R,并将其哈希添加到H
  • 当R已满时,比如M个条目,将其写入O。然后重复从F填充I,按照步骤3进行重复数据消除,然后写入O。在EOF(F)时,转至5
  • 重复(使用旧的O作为输入F,使用新的O作为输出):从F读取M行并复制到O。然后按照步骤2和3加载R和H,并像前面一样使用重复数据消除复制到EOF(F)。在每个O文件的开头将M设置为新的非重复行数
  • 请注意,在每次传递之后,O的前M行不包含重复项,并且这些M行中没有一行在O的其余部分中重复。因此,每次传递至少处理原始文件的
    1/k
    ,因此处理最多需要
    k


    更新1应使用单独的输出文件p,而不是重复写入和读回已处理的前导行,在每次传递结束时将进程缓冲区R附加到该文件中。当结果文件B几乎与a一样大时,这会将读写量减少一倍
    k/2
    ,或者当B比a小得多时,会减少一点;但它在任何情况下都不会增加I/O量。

    我认为CouchDB是一种NoSQL解决方案。您说过“a.txt”不适合内存。你知道A的唯一元素(即B中的结果)是否适合存储吗?我想他们不会,但如果他们这样做了,问题就大大简化了。B也不能放在内存中。你有Microsoft Access吗?这可以很容易地在Access中完成,即使使用txt文件也是如此。我需要的是算法,而不是实现。但是,文件的顺序与原始顺序不同。然而,没有-1,因为这可能并不坏。OP应该会告诉你。你可以用行号装饰文件,按你想重复消除的键排序,重复消除,然后按行号重新排序。我喜欢你的算法:)你是数学家吗?这是第一个不太明显的答案:程序员/分析师比数学家多。请随意投票支持我的答案!:)