【问题标题】:Remove rare words from a very large file从非常大的文件中删除稀有词
【发布时间】:2012-10-17 20:26:10
【问题描述】:

给定一个非常大的文本文件,我想删除文件中只出现一次的所有单词。有什么简单有效的方法吗?

最好的问候,

【问题讨论】:

  • 文件是否需要保持有序?列表排序了吗?
  • nltk 字数 -> 获取所有出现一次的单词 -> 使用正则表达式删除
  • 文件可能是GB大小,行数可能是几百万。输出文件不应包含频率为 1 的任何单词。换句话说,这些稀有词只是从文件中删除,其他一切都将保持不变。最好的问候,

标签: python linux file unix words


【解决方案1】:

您必须通过文件执行 2 次:

在通道 1 中:

  • 使用单词作为键并将它们的出现作为值来构建字典(即每次阅读一个单词时,将其在字典中的值加 1)
  • 然后对列表进行预处理以删除所有值大于 1 的键。这现在是您的“黑名单”

在通道 2 中:

  • 再次通读文件并删除黑名单中匹配的任何单词。

运行时:

  • 两次读取文件的线性时间。
  • 将每个单词添加到字典中/在第 1 步中增加其值需要 O(1)。
  • 将字典预处理到黑名单需要 O(n)。
  • 在第 2 步中查找黑名单需要 O(1)。

O(n) 复杂度

【讨论】:

  • Pass 2 再次通过文件,所以 O(N) 和 pass 1 一样。
  • 字典操作为O(1)
  • @ovgolovin 如果键的数量足够大,我相信它们是 O(log n);但是在这种情况下,如果我们假设一种自然语言,那么所有可能的有效词的集合将使得查找 O(1),因为这个集合是一个相对固定的数字。
  • @sampson-chen Dictionary 使用hash-table 实现。所以没有理由让O(log(n))变得复杂。
  • @sampson-chen 哦,不是O(n),而是O(1)
【解决方案2】:

2 次遍历文件是绝对必要的。但是,如果稀有词确实很少见,那么您可以在第二遍时跳过对文件的大部分进行标记。首先逐字逐句地遍历文件,并构建一个字典,其中包含找到的一次遇到的单词的位置或两次遇到的单词的占位符值。

MULTI_WORD = -1
word_locations = {}

for pos, word in tokenize(input_file):
    if word not in word_locations:
        word_locations[word] = pos
    else:
        word_locations[word] = MULTI_WORD

然后你可以过滤掉你需要编辑的位置,并在其余部分做一个普通的复制:

edit_points = [(pos, len(word)) for word, pos in word_locations.iteritems()
                                if pos != MULTI_WORD]

start_pos = 0
for end_pos, edit_length in edit_points:
    input_file.seek(start_pos)
    output_file.write(input_file.read(end_pos - start_pos))
    start_pos = end_pos + edit_length
input_file.seek(start_pos)
output_file.write(input_file.read())

您可能需要更多优化,例如块明智的复制过程以节省内存开销和没有编辑点的特殊情况。

【讨论】:

  • 你也可以使用内存映射,然后使用seek删除单词。
【解决方案3】:

如果没有具体的代码可以参考,很难知道,但一个好的起点可能是Natural Language Toolkit for Python

【讨论】:

  • 文件可能是GB大小,行数可能是几百万。输出文件不应包含频率为 1 的任何单词。换句话说,这些稀有词只是从文件中删除,其他一切都将保持不变。最好的问候,
  • 我认为@sampson-chen 的回答将最适合你。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-11-05
  • 2020-03-22
  • 2012-04-06
  • 2015-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多