Skip to main content
 首页 » 编程设计

python之使用列表推导式向字典中的值加一

2025年05月04日23linjiqin

我试图摆脱这个 for 循环,而是使用列表理解来给出相同的结果。

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 

我不确定这是否可行,但由于 +=1,我无法让它工作。我试过:

[freqdist[word.lower()] +=1 for word in nltk.word_tokenize(raw)] 

但这只会引发错误。谁能指出我正确的方向?

请您参考如下方法:

如果您想改变一个现有的列表/字典,使用列表/字典理解被认为是不好的风格,因为它会创建一个不必要的一次性列表/字典。

准确地说,我说的是以下内容:

>>> 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} 

如您所见,可以按照您的描述进行操作,但这不是您应该做的,因为

  • 很难阅读
  • 它创建一个未使用的一次性列表 [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} 

但是,我们现在的运行时复杂度不是最优的,因为对于 freqdist 中的每个键我们对 len(demo) 进行 O( demo ) 成员测试.

您可以使用set对于 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} 

我也不认为这个解决方案特别优雅。

总之,您的 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}) 

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