Python 将forloop转换为列表理解

Python 将forloop转换为列表理解,python,list-comprehension,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

我试图将以下内容转换为列表理解,但仍有困难:

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]

不幸的是,已经过了几个小时了,但我尝试过的方法似乎都不管用。对于这个问题,您甚至不需要任何列表/听写理解。只需使用一个按钮

如果你真的想用老式的方式来做,你可以做如下事情:

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
用作变量名。它隐藏了内置函数,使该函数无法使用,并可能导致难以调试的错误。

理解不是此工作的正确工具。A
集合。计数器是:

来自集合导入计数器的
>>
>>>计数=计数器(lorem_ipsum.split())
>>>打印(计数)
计数器({'Lorem':1,'ipsum':1,'dolor':1,'sit':1,'amet':1,'Concertetur':1,'Adipsing':1,'Elite':1})
>>>计数['Lorem']
1.
>>>计数['foo']
0

您可以使用计数进行此操作

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

你真正需要的是词典理解,而不是列表理解。它们很相似,但语法有点不同

# list comprehension
[foo for foo in stuff]

# dict comprehension
{key: val for key, val in some_tuple}
问题是,这对您试图解决的问题不起作用

理解可以作为
映射
,其中每个元素都以某种方式进行了转换,从而生成一个新集合;也可以作为
过滤器
,其中有一个新集合,其中一些元素可能已删除。这些是无状态操作

字数计算包括记录你已经看到的东西。这是一个
reduce
操作,您将状态保存在其他一些数据结构中,
在您的情况下计数

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

综上所述,下面是如何使用列表理解来计算单词。请不要在家里(或在工作中…尤其是在工作中…)尝试此功能


这是因为理解在幕后基本上是一个for循环,但是您仍然在更新状态变量,只是忽略了创建的实际列表。在这种情况下,它用增加的内存使用来换取可读性,这不是一个很好的选择。

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

[counts[word] += 1 if word in counts else counts[word] = 1 for word in words]
>>> 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}
尝试更新每个
单词的
计数。列表理解不是用来这样使用的

itertools.Counter
旨在解决您的问题,您可以使用计算每个元素的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
(如果
w
不在
d
,则替换为
0+1

这就暗示了你应该如何写你的理解清单:

[counts[word] += 1 if word in counts else counts[word] = 1 for word in words]
>>> 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]
是列表的实际返回值。字典
count
已更新,但不要这样做。除非使用结果,否则不要使用列表理解。

函数返回一个
dict
。您希望如何从列表理解中获得一个?似乎使用collections.Counter是更好的解决方案,因此感谢您的建议。不幸的是,我有一个特别的要求,使用“老式”的方法,所以我使用了你的理解版本,它工作得非常完美。谢谢。我也将避免使用str作为变量名-再次感谢您的建议。我恐怕我需要使用“错误的工具”,但我的观点是正确的。我会在有空的时候尝试使用你更好的方法:)谢谢你的解释和解决方案,非常有用。看起来我需要做一些关于列表和听写理解(以及集合)的阅读。这是一个很好的提示谢谢你的警告。考虑到这一点和其他答案的要旨,我肯定会尝试避免以这种方式使用理解。我修正了答案。