2013-07-23 7 views
6

Wydaje się to być tak oczywistą rzeczą, że czuję, że czegoś brakuje, ale jak się dowiedzieć, czy dwa różne klucze w tym samym słowniku mają dokładnie taką samą wartość? Na przykład, jeśli masz słownik test z kluczami a, b i c, a klucze a i b mają wartość 10, jak byś to rozgryzł? (W tym miejscu proszę przyjąć dużą liczbę kluczy, powiedzmy 100, i nie masz żadnej wiedzy na temat liczby duplikatów, jeśli istnieje wiele zestawów duplikatów lub jeśli w ogóle są duplikaty). Dzięki.Jak sprawdzić, czy dwa klucze w dyktafonie mają tę samą wartość?

+0

Nie powinno być żadnych duplikatów kluczy w dyktowaniu ... Chyba że masz na myśli, te, które są takie same między dwoma osobnymi dyktami. – Izkata

+0

klucze nie będą duplikować, ale różne klucze mogą mieć te same wartości.Próbuję zrozumieć, jak dowiedzieć się, które klucze mają te same wartości. – Kpower

+1

Myślę, że oznacza on wartości duplikatów dla różnych kluczy. Przynajmniej tak sugeruje przykład. – mr2ert

Odpowiedz

6

Aby wykryć wszystkich tych przypadkach:

>>> import collections 
>>> d = {"a": 10, "b": 15, "c": 10} 
>>> value_to_key = collections.defaultdict(list) 
>>> for k, v in d.iteritems(): 
...  value_to_key[v].append(k) 
... 
>>> value_to_key 
defaultdict(<type 'list'>, {10: ['a', 'c'], 15: ['b']}) 

@hivert sprawia, że ​​to doskonały punkt działa tylko wtedy, gdy wartości są hashable. Jeśli tak nie jest, nie ma fajnego rozwiązania O (n) (niestety). To jest najlepsze, co mogę wymyślić:

d = {"a": [10, 15], "b": [10, 20], "c": [10, 15]} 
values = [] 
for k, v in d.iteritems(): 
    must_insert = True 
    for val in values: 
     if val[0] == v: 
      val[1].append(k) 
      must_insert = False 
      break 
    if must_insert: values.append([v, [k]]) 

print [v for v in values if len(v[1]) > 1] #prints [[[10, 15], ['a', 'c']]] 
+0

@Ben dobry punkt, przy założeniu, że mam rozumieć co Kpower próbuje wykryć, mam edytowane w roztworze, który powinien rozwiązać problem. –

+0

Działa to również tylko wtedy, gdy wartości są nieosiągalne. Zastanów się na przykład, co się dzieje, gdy wartości są listami. – hivert

+0

@hivert yes Zauważyłem to z innych komentarzy. Nie ma ładnego (O (n)) rozwiązania problemu, jeśli wartości nie są nieosiągalne, o ile wiem. –

6
len(dictionary.values()) == len(set(dictionary.values())) 

to przy założeniu, że jedyną rzeczą, którą chcesz wiedzieć, czy istnieją zduplikowane wartości, nie których wartości są duplikaty, które jest co Przyjąłem z twojego pytania. Daj mi znać, jeśli źle zinterpretowałem pytanie.

Zasadniczo chodzi tylko o sprawdzenie, czy jakiekolwiek wpisy zostały usunięte, gdy wartości słownika zostały rzucone do obiektu, który z definicji nie ma żadnych duplikatów.

Jeśli powyższe nie działa dla swoich celów, powinno to być lepszym rozwiązaniem:

set(k for k,v in d.items() if d.values().count(v) > 1)) 

Zasadniczo druga wersja tylko sprawdza, czy istnieje więcej niż jeden wpis, który zostanie usunięty, jeśli spróbuj wyskoczyć z listy.

+0

Zadziała tylko to wartości są hashable – hivert

+0

@hivert Popraw mnie jeśli się mylę, ale nie jest równość już niejednoznaczne dla obiektów, które nie są hashable? –

+0

Przepraszam, jeśli moje pytanie było jasne. chciałem wiedzieć, jakie wartości były duplikaty – Kpower

1

wybudować kolejny dict Mapowanie wartości pierwszej dict do wszystkich klawiszy, które utrzymują, że wartość:

import collections 

inverse_dict = collections.defaultdict(list) 
for key in original_dict: 
    inverse_dict[original_dict[key]].append(key) 
+1

Działa to tylko wtedy, gdy wartości są nieosiągalne. – hivert

2
dico = {'a':0, 'b':0, 'c':1} 
result = {} 
for val in dico: 
    if dico[val] in result: 
     result[dico[val]].append(val) 
    else: 
     result[dico[val]] = [val] 
>>> result 
{0: ['a', 'b'], 1: ['c']} 

Następnie można filtrować na klucz wynikiem, że ma wartość (lista) z więcej niż jeden element, np Znaleziono duplikat:

+0

Dzięki, zmieniłem kod. – Ketouem

+0

@Ketouem to wynik tylko {} na początku? – Kpower

+0

Tak, rzeczywiście, mój zły, będę zmienić fragment – Ketouem

4

Możesz powiedzieć , które są duplikatami za pomocą odwrotnego indeksu - gdzie klucz jest duplikatem, a wartość jest zbiorem kluczy, które mają tę wartość (to zadziała jako ile wartości w słowniku wejściowego są hashable):

from collections import defaultdict 

d = {'w':20, 'x':10, 'y':20, 'z':30, 'a':10} 
dd = defaultdict(set) 

for k, v in d.items(): 
    dd[v].add(k) 

dd = { k : v for k, v in dd.items() if len(v) > 1 } 

dd 
=> {10: set(['a', 'x']), 20: set(['y', 'w'])} 

Od tego ostatniego wyniku jest to łatwe do uzyskania zestaw kluczy z dwóch wartości:

set.union(*dd.values()) 
=> set(['y', 'x', 'a', 'w']) 
0
keys = set() 
for key1 in d: 
    for key2 in d: 
     if key1 == key2: continue 
     if d[key1] == d[key2]: 
      keys |= {key1, key2} 

tj. To Θ (n²), co chcesz. Powodem jest to, że dykt nie zapewnia Θ (1) wyszukiwania klucza, któremu przypisano wartość. Więc lepiej przemyślcie swoje wybory struktury danych, jeśli to nie wystarczy.

Powiązane problemy