2014-08-28 90 views
0

樣品:複製一個字典的一部分,新的字典基於密鑰的列表上

d = { 
    "test": 1, 
    "sample": 2, 
    "example": 3, 
    "product": 4, 
    "software": 5, 
    "demo": 6, 
} 

filter_keys = ["test","sample","example","demo"] 

我想創建一個只包含從第一個字典,它的鍵出現在列表中的項目一個新的字典。換句話說,我想:

d2 = { 
    "test": 1, 
    "sample": 2, 
    "example": 3, 
    "demo": 6, 
} 

我可以用一個循環做到這一點:

d2 = {} 
for k in d.keys(): 
    if (k in filter_keys): 
     d2[k] = d[k] 

但這似乎非常「非Python化」。我也猜測,如果你有一個巨大的字典,說5,000個左右的項目,與新的字典相比,不斷增加的新項目會比較直接。

此外,你希望能夠處理錯誤。如果列表中包含的內容不是字典中的關鍵字,則應該忽略它。或者它可能會被添加到新的字典中,但值爲None。

有沒有更好的方法來實現這個目標?

+0

你已經問了很多問題而不接受這些問題的答案。你應該接受答案。 – EML 2014-09-09 22:54:27

回答

1

爲了獲得最佳性能,您應該遍歷列表中的按鍵,並檢查它們是否在字典而不是周圍的其他方法:

d2 = {} 
for k in list_of_keys: 
    if k in d: 
     d2[k] = d[k] 

這裏的好處是dict.__contains__in)上一個dict是O(1),而列表是O(N)。對於大型列表,這是一個巨大的好處(O(N)算法與O(N^2))。

我們可以稍微更簡潔與等效字典,理解表達上述循環:

d2 = {k: d[k] for k in list_of_keys if k in d} 

這將很可能略高於循環快,但可能不足以永遠不用擔心。也就是說,大多數python程序員會更喜歡這個版本,因爲它更簡潔且非常常見。

+0

+1最有效的解決方案 – 2014-08-28 19:00:04

+0

@EML,想想邏輯,爲什麼迭代完整的dict而不是僅僅四個列表項? – 2014-08-28 19:02:36

+0

對不起,我刪除了我的評論 - 我打算編輯它。這是否更有效取決於我們打算過濾的鍵是否實際上是字典中鍵的子集。篩選器列表可能大於字典中實際鍵的數量。當然,檢查字典是爲了獲得會員資格而不是列表,所以我編輯了我的評論以反映這一點。 – EML 2014-08-28 19:05:25

1

解釋的理解是這樣做的一種方法:

new_d = {k: v for k, v in d.items() if k in l} 

演示:

>>> d = { 
...  "test": 1, 
...  "sample": 2, 
...  "example": 3, 
...  "product": 4, 
...  "software": 5, 
...  "demo": 6, 
... } 
>>> 
>>> l = ["test","sample","example","demo"] 
>>> new_d = {k: v for k, v in d.items() if k in l} 
>>> new_d 
{'sample': 2, 'demo': 6, 'test': 1, 'example': 3} 
2

一個直接的方式做,這是與 「字典理解」:

filtered_dict = {key: value for key, value in d.items() if key in filter_keys} 

請注意,如果條件出現在理解結束時,它會過濾執行循環狀態ENT。根據按鍵的字典中的數字是否比您要篩選上按鍵的數量越多,這個版本可以更高效:

filtered_dict = {key: d[key] for key in filter_keysif key in d} 

在字典(key in d)檢查會員資格顯著的速度比檢查過濾器密鑰列表中的成員資格(key in filter_keys)。但是,哪種結果更快取決於過濾器關鍵字列表的大小(以及較小程度上的字典大小)。

相對蟒蛇辦法做到這一點沒有字典的理解與dict構造:

filtered_dict = dict([(key, value) for key, value in d.items() if key in filter_keys]) 

注意,這基本上等同於詞典理解,但如果你不熟悉的可能是更清晰詞典理解語法。

+0

不需要建立一個列表傳遞給字典構造函數 - 生成器表達式將會很好。 – mgilson 2014-08-28 18:37:48

+0

字典理解真棒。我一直使用列表解析,但從來不知道你可以用字典做同樣的事情。 – fdmillion 2014-08-28 18:40:09

+0

@fdmillion - 是的,他們被添加到python2.7以及設置解析,例如:'{x * x for x in something}' – mgilson 2014-08-28 18:47:43

0

按照問題你最後一部分:

或者,也許它被添加到新的字典,但與無的值。

l = ["test","sample","example","demo","badkey"] 
d = { 
    "test": 1, 
    "sample": 2, 
    "example": 3, 
    "product": 4, 
    "software": 5, 
    "demo": 6, 
} 


print {k: d.get(k) for k in l} 
{'test': 1, 'sample': 2, 'badkey': None, 'example': 3, 'demo': 6} 

您可以將默認的返回值傳遞給dict.get,它是None默認,但你可以將其設置爲d.get(k,"No_match")等等。或者你想要的任何值。

相關問題