[英]Test if dict contained in dict
對於python dicts,測試相等的工作正常如下:
first = {"one":"un", "two":"deux", "three":"trois"}
second = {"one":"un", "two":"deux", "three":"trois"}
print(first == second) # Result: True
但現在我的第二個dict包含一些我想忽略的附加鍵:
first = {"one":"un", "two":"deux", "three":"trois"}
second = {"one":"un", "two":"deux", "three":"trois", "foo":"bar"}
有沒有一種簡單的方法來測試第一個字典是否是第二個字典的一部分,包括它的所有鍵和值?
編輯1:
懷疑這個問題是如何測試字典是否包含某些鍵的重復,但我對測試鍵及其值感興趣。 只包含相同的鍵不會使兩個dicts相等。
編輯2:
好的,我現在用四種不同的方法得到了一些答案,證明了所有這些方法都有效。 由於我需要一個快速的過程,我測試了每個執行時間。 我創建了三個相同的詞組,包含1000個項目,鍵和值是長度為10的隨機字符串。 second
和third
得到一些額外的鍵值對, third
的最后一個非額外鍵得到一個新值。 所以, first
是second
的子集,但不是third
的子集。 使用10000次重復的模塊timeit
,我得到:
Method Time [s]
first.viewitems() <=second.viewitems() 0.9
set(first.items()).issubset(second.items()) 7.3
len(set(first.items()) & set(second.items())) == len(first) 8.5
all(first[key] == second.get(key, sentinel) for key in first) 6.0
我猜測最后一種方法是最慢的,但它已經到位2.但方法1擊敗了它們。
謝謝你的回答!
您可以使用字典視圖 :
# Python 2
if first.viewitems() <= second.viewitems():
# true only if `first` is a subset of `second`
# Python 3
if first.items() <= second.items():
# true only if `first` is a subset of `second`
字典視圖是Python 3中的標准 ,在Python 2中,您需要在標准方法前加上view
。 它們就像集合一樣,並且<=
測試其中一個是否是另一個的子集(或等於)。
Python 3中的演示:
>>> first = {"one":"un", "two":"deux", "three":"trois"}
>>> second = {"one":"un", "two":"deux", "three":"trois", "foo":"bar"}
>>> first.items() <= second.items()
True
>>> first['four'] = 'quatre'
>>> first.items() <= second.items()
False
這也適用於不可散列的值 ,因為鍵使得鍵值對已經是唯一的。 在這一點上,文檔有點令人困惑,但即使使用可變值(例如,列表),這也有效:
>>> first_mutable = {'one': ['un', 'een', 'einz'], 'two': ['deux', 'twee', 'zwei']}
>>> second_mutable = {'one': ['un', 'een', 'einz'], 'two': ['deux', 'twee', 'zwei'], 'three': ['trois', 'drie', 'drei']}
>>> first_mutable.items() <= second_mutable.items()
True
>>> first_mutable['one'].append('ichi')
>>> first_mutable.items() <= second_mutable.items()
False
您還可以將all()
函數與生成器表達式一起使用; 使用object()
作為標記來簡潔地檢測缺失值:
sentinel = object()
if all(first[key] == second.get(key, sentinel) for key in first):
# true only if `first` is a subset of `second`
但這不像使用字典視圖那樣具有可讀性和表現力。
all(k in second and second[k] == v for k, v in first.items())
如果你知道沒有任何值可以是None
,它將簡化為:
all(second.get(k, None) == v for k, v in first.items())
所以,你基本上想要檢查一個字典是否是另一個字典的子集。
first = {"one":"un", "two":"deux", "three":"trois"}
second = {"one":"un", "two":"deux", "three":"trois", "foo":"bar"}
def subset_dic(subset, superset):
return len(set(subset.items()) & set(superset.items())) == len(subset)
print(subset_dic(first, second))
打印:
True
如果您想抽象出子集/超集部分:
def subset_dic(dict1, dict2):
return len(set(dict1.items()) & set(dict2.items())) == len(min((dict1, dict2), key=len))
注意 :如果任何值是可變對象,則無法工作。 因此,您可以在函數中添加額外的步驟(將可變對象轉換為不可變模擬)以克服此限制。
#Update Ans:
方法-1:使用字典視圖:
正如Martijn所說,我們可以使用字典視圖來檢查這一點。 dict.viewitems()
充當集合。 我們可以在此交叉,聯合等上執行各種設置操作。(檢查此鏈接 。)
first.viewitems() <= second.viewitems()
True
我們檢查first
是否小於等於second
。 評估為True意味着first
是second.
個子集second.
METHOD-2使用集合的issubset()操作:
(免責聲明:此方法有一些冗余,並且要求所有值都是可清除的。建議遵循方法1來處理所有情況。感謝Martijn的建議。)
使用.items()
屬性獲取(鍵,值)元組的列表,然后使用集合的issubset()操作。
這將檢查鍵和相等。 。
>>> first = {"one":"un", "two":"deux", "three":"trois"}
>>> second = {"one":"un", "two":"deux", "three":"trois", "foo":"bar"}
>>> set(first.items()).issubset(second.items())
True
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.