【问题标题】:How to get unique words from a list quickly?如何快速从列表中获取唯一单词?
【发布时间】:2019-05-09 00:08:28
【问题描述】:

我有一个包含 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)

此代码提供了唯一的单词,但处理时间太长。每小时大约 50k 句。处理可能需要 3 天时间。

我也尝试过使用 lambda 函数:

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

但是,执行方面没有显着改善。请提出一个具有有效执行时间的更好的解决方案。欢迎提出并行处理建议。

【问题讨论】:

  • 如果单词已经是句子的元素,为什么还需要列表理解[word for word in sentence]?为什么不直接运行set(sentence)
  • 因为句子是连续的,然后我必须对它们进行标记。我有条件在发送到列表之前申请
  • 啊,感谢您更新示例 :)

标签: python lambda nlp nltk execution


【解决方案1】:

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

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 返回一个列表,我们的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)))

【讨论】:

  • 感谢您的回答。但我使用了 lambda 映射。比那更快吗?
  • @Bharathkumark,问题在于您在代码中对listset 进行了所有不必要的调用。同样在map 中使用函数而不是lambda 会使一切变得更快。
  • 我明白你的意思。让我试试这个:) 感谢您的详细解释和努力。
  • 对于 1.5 GB 大小的文件来说,速度非常快,谢谢!
猜你喜欢
  • 2020-03-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-04
  • 2020-09-23
  • 1970-01-01
  • 2022-01-20
相关资源
最近更新 更多