python - Test if dict contained in dict -
testing equality works fine python dicts:
first = {"one":"un", "two":"deux", "three":"trois"} second = {"one":"un", "two":"deux", "three":"trois"} print(first == second) # result: true
but second dict contains additional keys want ignore:
first = {"one":"un", "two":"deux", "three":"trois"} second = {"one":"un", "two":"deux", "three":"trois", "foo":"bar"}
is there simple way test if first dict part of second dict, keys , values?
edit 1:
this question suspected duplicate of how test if dictionary contains keys, i'm interested in testing keys and values. containing same keys not make 2 dicts equal.
edit 2:
ok, got answers using 4 different methods, , proved of them working. need fast process, tested each execution time. created 3 identical dicts 1000 items, keys , values random strings of length 10. second
, third
got key-value pairs, , last non-extra key of third
got new value. so, first
subset of second
, not of third
. using module timeit
10000 repetitions, got:
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) key in first) 6.0
i guessed last method slowest, it's on place 2. method 1 beats them all.
thanks answers!
you can use dictionary view:
# python 2 if first.viewitems() <= second.viewitems(): # true if `first` subset of `second` # python 3 if first.items() <= second.items(): # true if `first` subset of `second`
dictionary views standard in python 3, in python 2 need prefix standard methods view
. act sets, , <=
tests if 1 of subset of (or equal to) another.
demo in 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
this works non-hashable values too, keys make key-value pairs unique already. documentation little confusing on point, mutable values (say, lists) works:
>>> 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
you use all()
function generator expression; use object()
sentinel detect missing values concisely:
sentinel = object() if all(first[key] == second.get(key, sentinel) key in first): # true if `first` subset of `second`
but isn't readable , expressive using dictionary views.
Comments
Post a Comment