使用列表推导将一个值添加到字典中的值

San*_*uhh 1 python list-comprehension beautifulsoup nltk

我试图摆脱这个for循环,而是使用list comprehension来给出相同的结果.

fd= nltk.FreqDist()
html = requests.get("http://www.nrc.nl/nieuws/2015/04/19/louise-gunning-vertrekt-als-voorzitter-bestuur-uva/")
raw = BeautifulSoup(html.text).text
for word in nltk.word_tokenize(raw):
    freqdist[word.lower()] += 1
Run Code Online (Sandbox Code Playgroud)

我不确定它是否可能,但由于+ = 1,我无法让它工作.我试过了:

[freqdist[word.lower()] +=1 for word in nltk.word_tokenize(raw)]
Run Code Online (Sandbox Code Playgroud)

但这只会引发错误.有人能指出我正确的方向吗?

tim*_*geb 5

如果你想改变一个现有的列表/字典,使用列表/字典理解被认为是坏样式,因为它创建了一个不必要的一次性列表/字典.

确切地说,我在谈论以下内容:

>>> demo = ['a', 'b', 'c']
>>> freqdist = {'a': 0, 'b': 1, 'c': 2}
>>> [freqdist.__setitem__(key, freqdist[key] + 1) for key in demo]
[None, None, None]
>>> freqdist
{'a': 1, 'c': 3, 'b': 2}
Run Code Online (Sandbox Code Playgroud)

正如你所看到的,做你所描述的是可能的,但那不是你应该怎么做的原因

  • 很难读懂
  • 它会创建一个未使用的一次性列表 [None, None, None]
  • 列表推导应该用于构建您实际需要的新列表

使用字典理解创建新字典也很麻烦,因为不是每个值都应该递增(只有那些值demo).

可以做到

>>> demo = ['a', 'b', 'c']
>>> freqdist = {'a': 0, 'b': 1, 'c': 2}
>>> freqdist = {k:v + (k in demo) for k,v in freqdist.items()}
>>> freqdist
{'a': 1, 'c': 3, 'b': 2}
Run Code Online (Sandbox Code Playgroud)

但是,我们现在的运行时复杂性不是很理想,因为freqdist我们为每个键进行O(len(demo))成员资格测试demo.

可以使用setfor demo来将字典构建的复杂性降低到O(len(freqdist)),但前提是元素demo是唯一的.

>>> demo = set(['a', 'b', 'c'])
>>> freqdist = {'a': 0, 'b': 1, 'c': 2}
>>> freqdist = {k:v + (k in demo) for k,v in freqdist.items()}
>>> freqdist
{'a': 1, 'c': 3, 'b': 2}
Run Code Online (Sandbox Code Playgroud)

我认为这种解决方案也不是特别优雅.

总之,你的for循环非常好.唯一不错的选择是使用Counter您更新的对象:

>>> from collections import Counter
>>> demo = ['a', 'b', 'c']
>>> freqdist = Counter({'a': 0, 'b': 1, 'c': 2})
>>> freqdist.update(demo)
>>> freqdist
Counter({'c': 3, 'b': 2, 'a': 1})
Run Code Online (Sandbox Code Playgroud)

这是我个人使用的解决方案.