Reputation: 17040
I have a tuple with some names I want to match against one or more dictionaries.
t = ('A', 'B')
d1 = {'A': 'foo', 'C': 'bar'}
d2 = {'A': 'foo', 'B': 'foobar', 'C': 'bar'}
def f(dict):
"""
Given t a tuple of names, find which name exist in the input
dictionary dict, and return the name found and its value.
If all names in the input tuple are found, pick the first one
in the tuple instead.
"""
keys = set(dict)
matches = keys.intersection(t)
if len(matches) == 2:
name = t[0]
else:
name = matches.pop()
value = dict[name]
return name, value
print f(d1)
print f(d2)
The output is (A, foo)
in both cases.
This is not a lot of code, but it involves converting to a set, and then do an intersection. I was looking into some functools and haven't found anything useful.
Is there a more optimized way doing this using the standard library or built-in functions that I am not aware of?
Thanks.
Upvotes: 0
Views: 142
Reputation: 21595
for k in t:
try:
return k, dic[k]
except KeyError:
pass
If you (like me) don't like exceptions, and assuming None
is not a legitimate value:
for k in t:
res = dic.get(k)
if res is not None:
return k, res
Upvotes: 1
Reputation: 304147
def f(d):
"""
Given t a tuple of names, find which name exist in the input
dictionary d, and return the name found and its value.
If all names in the input tuple are found, pick the first one
in the tuple instead.
"""
for item in ((k, d[k]) for k in t if k in d):
return item
return ()
Upvotes: 1
Reputation: 8488
The "try-except" variants are ok, but i don't think they are optimal for your case. If you know that t has only 2 values (i.e: len(t) == 2 is invariant/is always True), you can get advantage of this and try something like this:
def f(t, dic):
if t[0] in dic:
return t[0], dic[t[0]]
elif t[1] in dic:
return t[1], dic[t[1]]
else: # Maybe any of t values are in dict
return None, None
Upvotes: -1
Reputation: 798606
def f(d):
try:
return next((x, d[x]) for x in t if x in d)
except StopIteration:
return ()
Upvotes: 1