2012-04-22 39 views
6

Potrzebowałem porównać 2 słowniki, aby znaleźć zestaw kluczy w jednym słowniku, który nie był w drugim.Zwięzły sposób na znalezienie "kluczowej" różnicy między 2 słownikami?

wiem, że Python ustawić obiekty wspierać:

set3=set1-set2 

ale nie mogę zrobić:

dict3=dict1-dict2 

czyli

missingKeys=dict1.keys()-dict2.keys() 

(byłem trochę zaskoczony przez ostatni punkt, ponieważ w Javie klucze są obiektami Set.) Jedno rozwiązanie to:

missingKeys=set(dict1.keys())-set(dict2.keys()) 

jest lepszy lub bardziej zwięzły sposób na zrobienie tego?

+0

myślę, że ostatnia linia jest dostatecznie zwięzły siebie, ale ... Chyba bardziej interesujące pytanie to "Jak usunąć wszystkie z w Y z X?" gdzie X i Y są listami. Byłoby użyteczne, gdyby na przykład duplikaty Z w X, które pojawiają się w Y, powinny zostać pozostawione same sobie. –

+0

@pst: Cóż, trochę dziwnie jest tworzyć obiekty ustawione, tylko po to, aby wykorzystać funkcję difference() ... –

+0

Z drugiej strony, ponieważ * jest * zestawem, może wykorzystać lepsze O ... różnice w wykazie za pomocą zrozumienia są łatwe, ale nieco bardziej rozwlekłe. Wciąż jednakowa wydajność, jeśli "sondowana" lista jest konwertowana na "zestaw". –

Odpowiedz

3

Może

[x for x in dict1.keys() if x not in dict2.keys()] 
+2

Myślę, że może to być nawet trochę bardziej zwięzłe: '[x dla x in dict1.keys() if x not in dict2]' ponieważ 'x in dict.keys()' jest takie samo jak 'x in dict' – mgilson

+0

@mgilson: tak długo, jak wskazywałeś, że 'x in dict' jest taki sam jak' x in dict.keys() ', to całkowita redukcja to' [x dla x w dykt1 if x not in dict2] '. –

+1

@SamGoldberg Masz rację.Powodem, dla którego o tym nie pomyślałem, jest to, że 'dla x in dict' nazywa metodę' __iter__' na dyktafonie, podczas gdy 'if x in dict' nazywa metodę' _contains__'. Tak więc w tym przypadku 'in' robi dwie różne rzeczy - po prostu mają ten sam rezultat. W każdym razie: '[x dla x w dykt1 if x not in dict2]' jest najbardziej zwięzłe, jak zauważyłeś. – mgilson

15

Python 2.7:

>>> d = {1:2, 2:3, 3:4} 
>>> d2 = {2:20, 3:30} 
>>> set(d)-set(d2) 
set([1]) 

Python 3.2:

>>> d = {1:2, 2:3, 3:4} 
>>> d2 = {2:20, 3:30} 
>>> d.keys()-d2.keys() 
{1} 
+0

+1 Och, podstępny Python 3.x! –

+0

Więc mówisz, że metoda Pythona 3.2 dict.keys() zwraca zestaw (jak Java)? Jakiś powód, dla którego wcześniejsza wersja tego nie zrobiła? –

+2

@SamGoldberg: nie, to faktycznie zwraca obiekt dict_keys, a nie zestaw, ale ma wiele operacji podobnych do zestawu. Zobacz, np. [to pytanie] (http://stackoverflow.com/questions/7296716/what-is-dict-keys-dict-items-and-dict-values). – DSM

4

przenośnych drodze robi Sugerowałbym użyciu dict.viewkeys w Pythonie 2.7 - to to backport Pythona 3.x dict.keys i jest automatycznie konwertowany przez 2to3.

Przykład:

>>> left = {1: 2, 2: 3, 3: 4} 
>>> right = {2: 20, 3:30} 
>>> left.viewkeys() - right.viewkeys() 
set([1]) 
1

To powinno działać w Pythonie 2.7 i 3.x:

>>> keys = getattr(dict, 'viewkeys', dict.keys) 
>>> left = {1: 2, 2: 3, 3: 4} 
>>> right = {2: 20, 3:30} 
>>> list(keys(left) - keys(right)) 
[1] 
Powiązane problemy