È possibile utilizzare un elenco di comprensione all'interno zip()
funzione:
>>> vals1, vals2 = zip(*[(dict1[k], v) for k, v in dict2.items() if k in dict1])
>>>
>>> vals1
(2, 3)
>>> vals2
(1, 2)
O come un approccio più funzionale utilizzando vista degli oggetti e operator.itemgetter()
si può fare:
>>> from operator import itemgetter
>>> intersect = dict1.viewkeys() & dict2.viewkeys()
>>> itemgetter(*intersect)(dict1)
(2, 3)
>>> itemgetter(*intersect)(dict2)
(1, 2)
Benchmark con risposta accettata:
from timeit import timeit
inp1 = """
commons = set(dict1).intersection(set(dict2))
list1 = [dict1[k] for k in commons]
list2 = [dict2[k] for k in commons]
"""
inp2 = """
zip(*[(dict1[k], v) for k, v in dict2.items() if k in dict1])
"""
inp3 = """
intersect = dict1.viewkeys() & dict2.viewkeys()
itemgetter(*intersect)(dict1)
itemgetter(*intersect)(dict2)
"""
dict1 = {(1, 2): 2, (2, 3): 3, (1, 3): 3}
dict2 = {(1, 2): 1, (1, 3): 2}
print 'inp1 ->', timeit(stmt=inp1,
number=1000000,
setup="dict1 = {}; dict2 = {}".format(dict1, dict2))
print 'inp2 ->', timeit(stmt=inp2,
number=1000000,
setup="dict1 = {}; dict2 = {}".format(dict1, dict2))
print 'inp3 ->', timeit(stmt=inp3,
number=1000000,
setup="dict1 = {}; dict2 = {};from operator import itemgetter".format(dict1, dict2))
Uscita:
inp1 -> 0.000132083892822
inp2 -> 0.000128984451294
inp3 -> 0.000160932540894
Per dizionari di lunghezza 10000 e gli elementi generati a caso, in 100 ciclo con:
inp1 -> 1.18336105347
inp2 -> 1.00519990921
inp3 -> 1.52266311646
Edit:
Come @Davidmh menzionato nel commento per aver rifiutato di sollevare un'eccezione per secondo approccio è possibile includere il codice in un'espressione try-except
:
try:
intersect = dict1.viewkeys() & dict2.viewkeys()
vals1 = itemgetter(*intersect)(dict1)
vals2 = itemgetter(*intersect)(dict2)
except TypeError:
vals1 = vals2 = []
Bello e pulito. – Lfod
Stavo per rispondere con qualcosa di simile. Bastonatemi! :) – DJGrandpaJ
Batti un secondo. Ma non è necessario chiamare i tasti o la seconda chiamata. –