I am trying to convert the following to list comprehension but struggling:
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))
So far I have tried a few variations on this:-
aString = lorem_ipsum
counts = dict()
words = aString.split
[counts[word] += 1 if word in counts else counts[word] = 1 for word in words]
Unfortunately, it has been some hours now but nothing I have tried seems to work
Warning! You are trying to use a side effect inside of a list comprehension:
[counts[word] += 1 if word in counts else counts[word] = 1 for word in words]
tries to update counts for every word. List comprehension are not meant to be used like that.
The class itertools.Counter is designed to solve your problem, and you can use a dict comprehension that counts every element (see other answers). But the dict comprehension has a O(n^2) complexity: for every element of the list, read the full list to find that element. If you want something functional, use a fold:
>>> 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}
For every word w, we udpate the current dictionary: d[w] is replaced by d[w]+1 (or 0+1 if w was not in d).
That gives a hint on how you could have written your list comprehension:
>>> 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}
As you see, [None, None, None, None, None, None, None, None] is the real return value of the list comprehension. The dictionary count was updated but do not do this!. Do not use a list comprehension unless you use the result.
Comprehensions aren't the right tool for this job. A collections.Counter is:
>>> 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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With