【问题标题】:Most efficient way to do multiple list comprehensions in Python在 Python 中进行多个列表推导的最有效方法
【发布时间】:2019-03-06 11:56:34
【问题描述】:

鉴于这三个列表推导,有没有比三个故意的集合更有效的方法来做到这一点?我相信在这种情况下 for 循环可能是不好的形式,但是如果我要遍历 rowsaslist 中的大量行,我觉得下面的内容效率不高。

cachedStopWords = stopwords.words('english')

rowsaslist = [x.lower() for x in rowsaslist]
rowsaslist = [''.join(c for c in s if c not in string.punctuation) for s in rowsaslist]
rowsaslist = [' '.join([word for word in p.split() if word not in cachedStopWords]) for p in rowsaslist]

将所有这些组合成一个理解语句是否更有效?从可读性的角度来看,我知道这可能是一团乱码。

【问题讨论】:

  • 您可以使用map()filter() 代替,但效率相同
  • 感谢大家对此的意见。我会尝试这些建议!

标签: python nltk list-comprehension


【解决方案1】:

您可以简单地定义 2 个函数并在一个列表理解中使用它们,而不是在同一个列表上迭代 3 次:

cachedStopWords = stopwords.words('english')


def remove_punctuation(text):
    return ''.join(c for c in text.lower() if c not in string.punctuation)

def remove_stop_words(text):
    return ' '.join([word for word in p.split() if word not in cachedStopWords])

rowsaslist = [remove_stop_words(remove_punctuation(text)) for text in rowsaslist]

我从未使用过stopwords。如果它返回一个列表,您最好先将其转换为set 以加快word not in cachedStopWords 测试。

最后,NLTK 包可能会帮助您处理文本。见@alvas' answer

【讨论】:

  • 我认为有一个更好的方法来处理这个问题,而不是执行嵌套循环来删除标点符号和停用词。
  • @alvas:你是对的。我已经添加了指向您答案的链接。
【解决方案2】:

我更喜欢这里的功能性方法*

' '.join(filter(lambda word: word not in cachedStopWords,
                ''.join(filter(lambda c: c not in string.punctuation,
                       map(str.lower, rowsaslist))).split())

它像罪恶一样丑陋,但真的没有办法让这个变得丑陋。注释非常适合这些大型一体化处理工作。

# removes punctuation, filters out stop words, and lowercases

这完美地解释了一切。


* 诚然,这可能是因为我在 Haskell 中玩得越来越多!

【讨论】:

  • 使用函数而不是 lambda 确实有助于提高可读性。那么就不需要 cmets 了。
【解决方案3】:

根据您是否需要按照输入的方式对结果列表进行相应排序,至少有两种方法可以解决此问题。

首先,您有两个似乎要删除的黑名单:

  • 标点符号
  • 停用词。

您想通过循环遍历字符来删除标点符号,而您想通过循环遍历标记来删除停用词。

假设输入是未标记的人类可读字符串。

为什么标点符号不能成为记号?这样你就可以通过循环记号来删除标点和停用词,即

>>> from nltk import word_tokenize
>>> from nltk.corpus import stopwords
>>> from string import punctuation
>>> blacklist = set(punctuation).union(set(stopwords.words('english')))
>>> blacklist
set([u'all', u'just', u'being', u'when', u'over', u'through', u'during', u'its', u'before', '$', u'hadn', '(', u'll', u'had', ',', u'should', u'to', u'only', u'does', u'under', u'ours', u'has', '<', '@', u'them', u'his', u'very', u'they', u'not', u'yourselves', u'now', '\\', u'nor', '`', u'd', u'did', u'shan', u'didn', u'these', u'she', u'each', u'where', '|', u'because', u'doing', u'there', u'theirs', u'some', u'we', u'him', u'up', u'are', u'further', u'ourselves', u'out', '#', "'", '+', u'weren', '/', u're', u'won', u'above', u'between', ';', '?', u't', u'be', u'hasn', u'after', u'here', u'shouldn', u'hers', '[', u'by', '_', u'both', u'about', u'couldn', u'of', u'o', u's', u'isn', '{', u'or', u'own', u'into', u'yourself', u'down', u'mightn', u'wasn', u'your', u'he', '"', u'from', u'her', '&', u'aren', '*', u'been', '.', u'few', u'too', u'wouldn', u'then', u'themselves', ':', u'was', u'until', '>', u'himself', u'on', u'with', u'but', u'mustn', u'off', u'herself', u'than', u'those', '^', u'me', u'myself', u'ma', u'this', u'whom', u'will', u'while', u'ain', u'below', u'can', u'were', u'more', u'my', '~', u'and', u've', u'do', u'is', u'in', u'am', u'it', u'doesn', u'an', u'as', u'itself', u'against', u'have', u'our', u'their', u'if', '!', u'again', '%', u'no', ')', u'that', '-', u'same', u'any', u'how', u'other', u'which', u'you', '=', u'needn', u'y', u'haven', u'who', u'what', u'most', u'such', ']', u'why', u'a', u'don', u'for', u'i', u'm', u'having', u'so', u'at', u'the', '}', u'yours', u'once'])
>>> sent = "This is a humanly readable string, that Tina Guo doesn't want to play"
>>> [word for word in word_tokenize(sent) if word not in blacklist]
['This', 'humanly', 'readable', 'string', 'Tina', 'Guo', "n't", 'want', 'play']

如果您不需要输入的单词顺序,使用set().difference 函数可以加快您的代码速度:

>>> set(word_tokenize(sent)).difference(blacklist)
set(['humanly', 'play', 'string', 'This', 'readable', 'Guo', 'Tina', "n't", 'want'])

或者,如果您不想标记字符串,可以使用str.translate 删除标点符号,这肯定比遍历字符更有效:

>>> sent
"This is a humanly readable string, that Tina Guo doesn't want to play"
>>> sent.translate(None, punctuation)
'This is a humanly readable string that Tina Guo doesnt want to play't
>>> stoplist = stopwords.words('english')
>>> [word for word in sent.translate(None, punctuation).split() if word not in stoplist]
['This', 'humanly', 'readable', 'string', 'Tina', 'Guo', 'doesnt', 'want', 'play']

【讨论】:

    【解决方案4】:

    按照您目前的方式,每个列表将在创建下一个列表之前完全创建。您可以通过从列表推导切换到生成器表达式来解决这个问题(注意使用() 而不是[]):

    rowsaslist = (x.lower() for x in rows as list) 
    rowsaslist = (''.join(c for c in s if c not in string.punctuation) for s in rows as list) 
    rowsaslist = (' '.join([word for word in p.split() if word not in cachedStopWords]) for p in rowsaslist) 
    

    这将创建 3 个生成器,而不是创建列表。每个生成器只会根据需要生成一个值,而不是一次严格地创建每个列表。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-20
      • 1970-01-01
      • 2014-03-31
      • 1970-01-01
      • 2020-09-14
      相关资源
      最近更新 更多