[英]Efficiency: 2D-list to dictionary in python
我有一個二維列表。
l = [[100, 1], [43, 2], [201, 1], [5, 7], ...]
我想將列表轉換為字典,其中第二個元素作為鍵。 每個鍵的值應該是所有第一個元素的列表,這些元素將鍵作為第二個元素。 此示例列表的字典應如下所示:
{
1: [100, 201],
2: [43],
7: [5],
...
}
對於這種轉換,我有兩種解決方案。 其中哪一個更有效,為什么? 另外:還有其他更有效的解決方案嗎?
解決方案1:
d = {}
for elem in l:
if elem[1] in d:
d[elem[1]].append(elem[0])
else:
d[elem[1]] = [elem[0]]
解決方案2:
d = {}
for elem in l:
d[elem[1]] = []
for elem in l:
d[elem[1]].append(elem[0])
你有兩個解決方案沒有錯,它們很好而且高效:
從理論的角度來看,它們是相同的。 運行時間我敢打賭它們也非常接近。 可以改進第一個解決方案的更pythonic方式(請求寬恕而不是許可,感謝@tobias_k)是:
d = {}
for elem in l:
try:
d[elem[1]].append(elem[0])
except KeyError:
d[elem[1]] = [elem[0]]
如果您有許多重復的鍵,這會更好,因為異常的開銷將比所有 if(並且只有一次查找)小得多,因此這將取決於所討論的實際列表。 如果您選擇此解決方案,您可能需要閱讀defaultdict 。
一些新信息
我的猜測錯了! 盡管理論上它們是相同的,並且看起來操作量相同,但還是有區別的。 我猜這與 Python 優化if
語句的能力有關。
使用timeit模塊標記您的第一個方法a
,第二個b
和我提供的c
,我為兩個列表對這些方法計時:
l1=[(x,y) for x,y in zip(range(1000),range(1000,2000)]
l1=[(x,2) for x,y in range(1000)]
l1
結果:
方法a
最快。 慢 30% 的是b
,另外 30% 是c
。
l2
結果:
方法a
和b
幾乎相同(a 仍然快一點),而c
比兩者都快一點(這是我們預期的)。
我會說出於實際目的,第一個版本比第二個更好,但如果你有很多重復鍵,3d 會是最好的。 最重要的是,理論一切都很好,但實際上最好的方法是依賴於列表的。
第一個解決方案更有效,因為它需要 O(n) 時間來完成:if 語句是 O(1),因為字典查找是 O(1)。
第二個解決方案也是 O(n) 但它運行了兩次,所以 O(n+n)。
在第一個解決方案中,您可以跳過 if 語句並直接附加 elem[0],並添加一個 try except 塊。
我認為解決方案 1比解決方案 2更有效,因為它只有一個循環。 我認為您可以嘗試以下代碼,它可能比解決方案 1更有效
l = [[100, 1], [43, 2], [201, 1], [5, 7]]
d = {}
for k, v in l:
d.setdefault(v, []).append(k)
print(d)
它給出了這樣的 o/p:
{1: [100, 201], 2: [43], 7: [5]}
l = [[100, 1], [43, 2], [201, 1], [5, 7]]
d = dict(l)
print(d)
它會給你輸出為{100: 1, 43: 2, 201: 1, 5: 7}
您的兩個解決方案將具有相同的 O( n )。 但是你可以使用collections.defaultdict
:
from collections import defaultdict
l = [[100, 1], [43, 2], [201, 1]]
d = defaultdict(list)
for v, k in l:
d[k].append(v)
# defaultdict(list, {1: [100, 201], 2: [43]})
一些基准測試:
from collections import defaultdict
import numpy as np
l = np.random.randint(1, 100, [int(1e7), 2])
def dd(l):
d = defaultdict(list)
for i in l:
d[i[1]].append(i[0])
return d
def op(l):
d = {}
for elem in l:
if elem[1] in d:
d[elem[1]].append(elem[0])
else:
d[elem[1]] = [elem[0]]
return d
%timeit dd(l) # 1 loop, best of 3: 8.22 s per loop
%timeit op(l) # 1 loop, best of 3: 9.47 s per loop
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.