是否可以使用列表理解来缩短这一点?

时间:2013-12-07 22:39:11

标签: python list

我正在处理一个大文本文件,作为输出,我有一个单词列表:

['today', ',', 'is', 'cold', 'outside', '2013', '?', 'December', ...]

我接下来想要实现的是将所有内容转换为小写,删除属于stopset的所有单词(常用单词)并删除标点符号。我可以通过3次迭代来做到这一点:

lower=[word.lower() for word in mywords]
removepunc=[word for word in lower if word not in string.punctuation]
final=[word for word in removepunc if word not in stopset]

我尝试使用

[word for word in lower if word not in string.punctuation or word not in stopset]

实现最后2行代码应该做的但是它不起作用。我的错误在哪里,有没有更快的方法来实现这一点,而不是遍历列表3次?

8 个答案:

答案 0 :(得分:2)

如果您的代码按预期工作,我认为这不是一个好主意。现在它具有良好的可读性,可以通过其他处理轻松修改。单行是有利于获得更多的投票,你将很难在一段时间后理解它的逻辑。

您可以使用生成器而不是列表替换中间步骤,以使计算工作一次,而不是生成多个列表:

lower = (word.lower() for word in mywords)
removepunc = (word for word in lower if word not in string.punctuation)
final = [word for word in removepunc if word not in stopset]

答案 1 :(得分:1)

你当然可以压缩逻辑:

final = [word for word in map(str.lower, mywords)
         if word not in string.punctuation and word not in stopset]

例如,如果我定义stopset = ['if'],我会得到:

 ['today', 'cold', 'outside', '2013', 'december']

答案 2 :(得分:0)

这是相同的单一列表理解,虽然我同意烷基,你已经拥有的东西更清楚:

final = [lower_word for word in mywords for lower_word in (word.lower(),) if lower_word not in string.punction and lower_word not in stopset]

答案 3 :(得分:0)

请注意,列表推导不是大文件的最佳选择,因为整个文件必须加载到内存中。

而是做Read large text files in Python, line by line without loading it in to memory

之类的事情
with open("log.txt") as infile:
    for line in infile:
        if clause goes here:
            ....

答案 4 :(得分:0)

我猜最快的方法是尝试尽可能多地将计算从Python移动到C.首先预先计算禁用字符串集。这只需要完成一次。

avoid = set(string.punctuation) | set(x.lower() for x in stopset)

然后让set减法操作尽可能多地进行过滤

final = set(x.lower() for x in mywords) - avoid

在开始之前将整个单词源一次转换为小写也可能会提高速度。在这种情况下,代码将是

final = set(mywords) - avoid

答案 5 :(得分:0)

您可以使用map折叠.lower处理

final = [word for word in map(str.lower, mywords) if word not in string.punctuation and word not in stopset]

您只需将string.punctuation添加到stopset,然后就会变为

final = [word for word in map(str.lower, mywords) if word not in stopset]

您确定不想保留输出中单词的大小写吗?

答案 6 :(得分:0)

  

有没有更快的方法来实现这一点,而不是迭代   列出3次?

将johnsharpe的代码转换为生成器。这可能会大大加快使用速度并降低内存使用量。

import string
stopset = ['is']
mywords = ['today', ',', 'is', 'cold', 'outside', '2013', '?', 'December']
final = (word.lower() for word in mywords if (word not in string.punctuation and 
                                              word not in stopset))
print "final", list(final) 

要在迭代器之外显示调试结果,请使用此示例中的list

答案 7 :(得分:0)

如果你使用过滤器,你可以使用一个列表理解来实现它,并且更容易阅读。

final = filter( lambda s: s not in string.punctation and s not in stopset  ,[word.lower() for word in mywords])