如何快速从列表中获取唯一的单词?

How to get unique words from a list quickly?

我有一个包含 300 万个句子(大约)的文件。每个句子大约有 60 个单词。我想把所有的词组合起来,从中找出独特的词。

我尝试了以下代码:

 final_list = list()
 for sentence in sentence_list:
     words_list = nltk.word_tokenize(sentence)
     words = [word for word in words_list if word not in stopwords.words('english') ]
     final_list = final_list + set(words)

此代码提供了独特的字词,但处理时间太长。每小时大约 5 万个句子。处理时间可能需要 3 天。

我也尝试使用 lambda 函数:

    final_list = list(map(lambda x: list(set([word for word in sentence])) ,sentence_list))

但是,执行力并没有明显的提升。请提出有效执行时间的更好解决方案。欢迎并行处理建议。

您需要懒惰地完成所有操作,并使用尽可能少的中间列表(减少分配和处理时间)。 文件中的所有唯一单词:

import itertools
def unique_words_from_file(fpath):
    with open(fpath, "r") as f:
        return set(itertools.chain.from_iterable(map(str.split, f)))

让我们在这里解释一下这些想法。

文件对象是可迭代对象,这意味着您可以迭代文件的行!

然后我们想要每行的单词,这就是拆分它们。在这种情况下,我们使用 Python3 中的 map(或 Python2 中的 itertools.imap)来创建一个对象,该对象在我们的文件行上进行计算。 mapimap 也是惰性的,这意味着默认情况下不会分配任何中间列表,这很棒,因为我们不会在不需要的东西上花费任何资源!

由于 str.split returns 一个列表,我们的 map 结果将是一系列字符串列表,但我们需要遍历每个字符串。为此,无需构建另一个 list,我们可以使用 itertools.chain 来展平该结果!

最后,我们调用 set,它将遍历这些单词并为每个单词保留一个单词。瞧!

让我们一起改进吧!我们可以让 str.split 也懒惰吗? 是的!检查这个 SO answer:

import itertools
import re

def split_iter(string):
    return (x.group(0) for x in re.finditer(r"[A-Za-z']+", string))

def unique_words_from_file(fpath):
    with open(fpath, "r") as f:
        return set(itertools.chain.from_iterable(map(split_iter, f)))