簡體   English   中英

通過dict理解增加dict值

[英]Incrementing dict values with dict comprehension

我正在嘗試使用dict理解和python中的三元運算來執行以下表達式:

for num in ar:
     if num in seen_dict:
         seen_dict[num] += 1
     else:
         seen_dict[num] = 1

我嘗試了這個:

seen_dict = { num: seen_dict[num] += 1 for num in ar if num in seen_dict else seen_dict[num] = 1}

及其幾個排列,但我不斷收到語法錯誤。 可以做我想做的嗎?

更新

這是正確的語法,但我的dict並非僅返回1:: seen_dict = { num: (seen_dict[num] + 1) if num in seen_dict else 1 for num in ar }

有人可以解釋為什么這與for循環的功能不同嗎? 謝謝。

別。 似乎使用dict理解應該是一個好主意,但這實際上是一個可怕的陷阱。 使用collections.Counter

import counts

seen_dict = collections.Counter(ar)

或者,如果您不想這樣做,請堅持循環。

嘗試使用dict理解的問題是dict理解沒有良好的方式來維持狀態或交錯每個鍵的值的計算。 每個值必須在單個表達式中計算。 相反,解決計數問題的最佳方法是對ar進行一次傳遞,並隨需更新每個元素的計數。

理解的限制會導致效率極低的嘗試,例如

seen_dict = {val: ar.count(val) for val in ar}

這使得若干越過的ar等於長度ar ,或稍微更有效,但仍可怕次優

seen_dict = {val: ar.count(val) for val in set(ar)}

只需傳遞len(set(ar)) ,或者對於更熟悉標准庫的人來說

from itertools import groupby
seen_dict = {val: sum(1 for _ in group) for val, group in groupby(sorted(ar))}

至少不是二次時間,但長度為n ar仍為O(nlogn)。

如果我們使用輸入list(range(10000))對這四個代碼片段進行計時

from collections import Counter
from itertools import groupby
from timeit import timeit

ar = list(range(10000))

print(timeit('Counter(ar)', number=1, globals=globals()))
print(timeit('{val: ar.count(val) for val in ar}', number=1, globals=globals()))
print(timeit('{val: ar.count(val) for val in set(ar)}', number=1, globals=globals()))
print(timeit('{val: sum(1 for _ in group) for val, group in groupby(sorted(ar))}',
             number=1, globals=globals()))

我們得到以下輸出:

0.0005530156195163727
1.0503493696451187
1.0463058911263943
0.00422721728682518

Counter在半毫秒內完成,而count片段都占用一秒以上。 (該set版本似乎具有較低的運行時由於某種首次運行效果減慢其他版本;交換的順序set和非set版本通常逆轉這些版本的相對定時的重復數據刪除。 set沒有按由於輸入沒有重復項,因此對測試沒有幫助。)

對於更長的輸入,依賴count將更加昂貴。 依靠count可能很容易需要幾天的時間, Counter仍會在一秒鍾之內完成輸入。

在這里,它實際上比我想象的要簡單。 基本上,您想要的是列表中某件事發生的次數,您可以通過說ar.count(num) 您可以輕松地做到這一點,而無需三元運算符,例如:

ar = [1,2,3,2]
seen_dict = { num:ar.count(num) for num in ar}
print(seen_dict)# {1:1, 2:2, 3:1}

似乎您正在嘗試獲取列表中所有值的外觀。 (如果不是,請讓我知道。)這是我將如何處理的方法:

seen_dict = {num: arr.count(num) for num in list(set(arr))}

一個解釋:

  • arr.count(num)list.count(element)方法返回listelement的出現次數
  • set(arr) :創建一個set對象,將其轉換回列表時將刪除所有重復項,換句話說,將獲取列表的所有不同值
  • list(set(arr))在不同的值arr

字典回報將有鍵值對number - # of appearances of number in arr

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM