我有一个包含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))
但是,执行没有明显改善。请提出一个有效的执行时间更好的解决方案。欢迎提出并行处理建议。
答案 0 :(得分:3)
您需要懒惰地做所有事情,并使用尽可能少的中间列表,并尽可能减少重复次数和处理时间。 文件中的所有唯一词:
import itertools
def unique_words_from_file(fpath):
with open(fpath, "r") as f:
return set(itertools.chain.from_iterable(map(str.split, f)))
让我们在这里解释一下想法。
文件对象是可迭代的对象,这意味着您可以遍历文件的每一行!
然后,我们希望每一行中的单词都被分开。在这种情况下,我们使用map
中的Python3
(或itertools.imap
中的Python2
)来创建一个对象,并在文件行上进行该计算。 map
和imap
也是懒惰的,这意味着默认情况下不会分配任何中间列表,这真是太棒了,因为我们不会在不需要的东西上花费任何资源!
由于str.split
返回一个列表,因此我们的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)))