Python:如何对多个嵌套列表进行列表推导?

Python: how to do this list comprehension with multiple nested lists?

我正在处理需要分解为句子标记列表的文本,这些句子标记本身又分解为单词标记。例如:

raw_text = "the cat in the hat.  green eggs and ham.  one fish two fish."

我还有一个要从文本中删除的停用词列表:

stopwords = ['the', 'and', 'in']

我正在使用 nltk 模块进行列表理解:

from nlkt import sent_tokenize, word_tokenize

sentence_tokens = [word_tokenize(sentence) for sentence in sent_tokenize(raw_text)]

这会产生以下结果:

[['the', 'cat', 'in', 'the', 'hat', '.'], ['green', 'eggs', 'and', 'ham', '.'], ['one', 'fish', 'two', 'fish', '.']]

我可以用嵌套的 for 循环过滤掉停用词:

for sentences in sentence_tokens:
    for word in sentences:
        if word in stop:
            sentences.remove(word)

我遇到的困难是将这些全部组合成一个列表推导式,这样会更简洁一些。有什么建议吗?谢谢!

停用词设为set,然后您可以使用list comp从每个子列表中过滤掉那些在停用词集中:

stopwords = {'the', 'and', 'in'}


l = [['the', 'cat', 'in', 'the', 'hat', '.'], ['green', 'eggs', 'and', 'ham', '.'], ['one', 'fish', 'two', 'fish', '.']]


l[:] = [[word for word in sub if word not in stopwords] for sub in l]

输出:

[['cat', 'hat', '.'], ['green', 'eggs', 'ham', '.'], ['one', 'fish', 'two', 'fish', '.']]

使用 l[:] 意味着我们将改变原来的 object/list,如果我们将它分解成一个 for 循环:

# for each sublist in l
for sub in l:
    # for each word in the sublist, keep it only if it is not in stopwords 
    sub[:] =  [word for word in sub if word not in stopwords]

你自己的代码也有一个错误,你不应该通过删除元素来迭代和改变列表,你需要制作一个副本或者我们也可以使用 reversed:

for sentences in l:
    for word in reversed(sentences):
        if word in stopwords:
            sentences.remove(word)

当你从左边开始删除一个元素时,你最终可能会删除错误的元素,因为循环开始时某个指针指向的内容可能不一样,所以在以后的删除中你可以删除错误的元素.

提示:此任务不需要 NLTK。一个简单的 Python 逻辑就可以了。 这是从文本中删除停用词的更简洁的方法。我在这里使用 Python 2.7。

当您需要字符串而不是单词列表时:

raw_text = "the cat in the hat.  green eggs and ham.  one fish two fish."
stopwords = ['the', 'and', 'in']
clean_text = " ".join(word for word in raw_text.split() if word not in stopwords)

当您需要单词列表时:

raw_text = "the cat in the hat.  green eggs and ham.  one fish two fish."
stopwords = ['the', 'and', 'in']
clean_list = [word for word in raw_text.split() if word not in stopwords]