2017-05-02 36 views
1

我想擺脫這個循環,而是使用列表理解給出相同的結果。使用列表理解添加一個字典中的值

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)] 

但是這隻會引發錯誤。任何人都可以將我指向正確的方向嗎?

+3

使用[計數器](HTTPS: //docs.python.org/2/library/collections.html#collections.Counter)? – asongtoruin

+0

列表理解創建一個新列表。看起來你不想在這裏創建一個列表。 – ikkuh

+5

'for'循環出了什麼問題?列表解析是爲了創建列表,而不是'for'循環的替代;它看起來像你試圖利用副作用。 – roganjosh

回答

5

如果你想要mutate現有的列表/字典,使用列表/字典理解被認爲是不好的風格,因爲它創建了一個不必要的一次性列表/字典。

準確地說,我說的是以下幾點:

>>> 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]
  • 列表解析應該用來建立一個新的列表,你實際上n eed

由於不是每個值都應該增加(只有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我們爲demo做一個O(len(demo))成員測試每個鍵。

可以使用setdemo到字典建設的複雜度降低到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}) 

這是我個人使用的解決方案。

0

這工作:

>>> txt = 'Hello goodbye hello GDby Dog cat dog' 
>>> txt_new = txt.lower().split() 
>>> print txt_new 
['hello', 'goodbye', 'hello', 'gdby', 'dog', 'cat', 'dog'] 

現在使用collections

>>> import collections 
>>> collections.Counter(txt_new) 
Counter({'hello': 2, 'dog': 2, 'gdby': 1, 'cat': 1, 'goodbye': 1}) 

如果不允許使用collections.Counter則:

>>> {word: txt_new.count(word) for word in set(txt_new)} 
{'goodbye': 1, 'dog': 2, 'hello': 2, 'gdby': 1, 'cat': 1} 
相關問題