将forloop转换为列表理解

时间:2019-05-06 19:38:51

标签: python list-comprehension

我正在尝试将以下内容转换为列表理解方法,但仍然很麻烦:

lorem_ipsum = """Lorem ipsum dolor sit amet, consectetur adipiscing elit."""

def word_count2(str):
    counts = dict()
    words = str.split() 

    for word in words:
        if word in counts:
            counts[word] += 1
        else:
            counts[word] = 1

    return counts

print(word_count2(lorem_ipsum))

到目前为止,我已经对此进行了一些尝试:-

aString = lorem_ipsum

counts = dict()
words = aString.split

[counts[word] += 1 if word in counts else counts[word] = 1 for word in words]

不幸的是,现在已经有几个小时了,但我尝试过的任何方法似乎都没有效果

5 个答案:

答案 0 :(得分:3)

警告!您正在尝试在列表理解中使用副作用:

[counts[word] += 1 if word in counts else counts[word] = 1 for word in words]

尝试为每个counts更新word。列表理解并不是要那样使用。

itertools.Counter旨在解决您的问题,您可以使用dict理解来计算每个元素(请参阅其他答案)。但是dict理解的复杂度为O(n ^ 2):对于列表中的每个元素,请阅读完整列表以查找该元素。如果您希望某些功能起作用,请使用折叠:

>>> lorem_ipsum = """Lorem ipsum dolor sit amet, consectetur adipiscing elit."""
>>> import functools
>>> functools.reduce(lambda d, w: {**d, w: d.get(w, 0)+1}, lorem_ipsum.split(), {})
{'Lorem': 1, 'ipsum': 1, 'dolor': 1, 'sit': 1, 'amet,': 1, 'consectetur': 1, 'adipiscing': 1, 'elit.': 1}

对于每个单词w,我们都会覆盖当前词典:d[w]d[w]+1替换(如果0+1不在{{1中,则替换为w }}。

这提示您如何编写列表理解:

d

如您所见,>>> counts = {} >>> [counts.update({word: counts.get(word, 0) + 1}) for word in lorem_ipsum.split()] [None, None, None, None, None, None, None, None] >>> counts {'Lorem': 1, 'ipsum': 1, 'dolor': 1, 'sit': 1, 'amet,': 1, 'consectetur': 1, 'adipiscing': 1, 'elit.': 1} 是列表推导的实际返回值。字典[None, None, None, None, None, None, None, None]已更新,但不要这样做!。除非使用结果,否则不要使用列表推导。

答案 1 :(得分:2)

对于这个问题,您甚至不需要任何列表/字典理解。只需使用collections.Counter

from collections import Counter
counts = Counter(lorem_ipsum.split())
# >>> print(counts)
# Counter({'ipsum': 1, 'amet,': 1, 'sit': 1, 'elit.': 1, 'consectetur': 1, 'adipiscing': 1, 'dolor': 1, 'Lorem': 1})

如果您真的想要以老式的方式进行操作,则可以执行以下操作:

words = lorem_ipsum.split()
counts = { word: words.count(word) for word in words }
# >>> print(counts)
# {'ipsum': 1, 'amet,': 1, 'sit': 1, 'elit.': 1, 'consectetur': 1, 'adipiscing': 1, 'dolor': 1, 'Lorem': 1}

此外,请勿使用str作为变量名。它遮盖了内置的str函数,这使该函数不可用,并可能导致难以调试的错误。

答案 2 :(得分:2)

理解不是这项工作的正确工具。 collections.Counter是:

>>> from collections import Counter
>>> counts = Counter(lorem_ipsum.split())
>>> print(counts)
Counter({'Lorem': 1, 'ipsum': 1, 'dolor': 1, 'sit': 1, 'amet,': 1, 'consectetur': 1, 'adipiscing': 1, 'elit.': 1})
>>> counts['Lorem']
1
>>> counts['foo']
0

答案 3 :(得分:2)

您真正要的是字典理解,而不是列表理解。它们相似,但语法略有不同

# list comprehension
[foo for foo in stuff]

# dict comprehension
{key: val for key, val in some_tuple}

麻烦的是,这对于您要解决的问题不起作用。

推论可以是map(在其中以某种方式转换每个元素而生成一个新集合),或者是filter(在其中可能会删除某些元素的新集合中)。这些是无状态操作。

字数统计涉及跟踪您已经看过的事物。这是一个reduce操作,您可以将状态保留在其他数据结构中,以counts为例。

正如其他答案所言,collections.Counter是解决此问题的“正确”方法。

话虽如此,以下是使用列表理解来计算单词数的方法。请不要在家中(或在工作中……尤其是在工作中……)不尝试

>>> lorem_ipsum = """
... Lorem ipsum dolor sit amet, consectetur adipiscing elit.
... """ * 2
>>> result = {}
>>> words = lorem_ipsum.split()
>>> [result.update({word: result.get(word, 0) + 1}) for word in words]
[None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None]
>>> result
{'consectetur': 2, 'ipsum': 2, 'amet,': 2, 'adipiscing': 2, 'sit': 2, 'elit.': 2, 'dolor': 2, 'Lorem': 2}

之所以起作用,是因为理解力基本上是幕后的for循环,但是您仍在更新状态变量,而忽略了实际创建的列表。在这种情况下,为了获得可读性,它以增加内存使用量为代价,而不是一个不错的选择。

答案 4 :(得分:0)

您可以为此使用count。

lorem_ipsum = """
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
"""

word = {word:lorem_ipsum.split().count(word) for word in lorem_ipsum.split()}
print word