Biorąc pod uwagę taki słownik:
my_map = {'a': 1, 'b': 2}
Jak można odwrócić tę mapę, aby uzyskać:
inv_map = {1: 'a', 2: 'b'}
python
dictionary
mapping
reverse
Brian M. Hunt
źródło
źródło
my_map.items()
działaThe order-preserving aspect of this new implementation is considered an implementation detail and should not be relied upon
. Nie ma gwarancji, że tak pozostanie, więc nie pisz kodu polegającego naDict
takim samym zachowaniu jakOrderedDict
.Zakładając, że wartości w dykcie są unikalne:
źródło
iteritems()
zostanie wyprowadzona, więc można założyć, że arbitralny klucz zostanie przypisany do wartości nieunikalnej, w sposób, który będzie w oczywisty sposób odtwarzalny w pewnych warunkach, ale ogólnie nie.iteritems()
metody i takie podejście nie zadziała; użyjitems()
tam zamiast tego, jak pokazano w zaakceptowanej odpowiedzi. Również tłumaczenie ze słownika uczyniłoby to ładniejszym niż dzwonieniedict
.Jeśli wartości w
my_map
nie są unikalne:źródło
inv_map.get(v, [])
zwraca listę, która już została dodana, jeśli taka istnieje, więc przypisanie nie resetuje się do pustej listy.setdefault
byłby jednak ładniejszy.inv_map.setdefault(v, set()).add(k)
.my_map.items()
zamiastmy_map.iteritems()
.Aby to zrobić, zachowując typ mapowania (zakładając, że jest
dict
todict
podklasa lub podklasa):źródło
Spróbuj tego:
(Zauważ, że dokumenty Pythona dotyczące widoków słownika wyraźnie to gwarantują
.keys()
i.values()
mają ich elementy w tej samej kolejności, co pozwala na działanie powyższego podejścia.)Alternatywnie:
lub używając rozumienia słownika w Pythonie 3.0
źródło
Kolejny, bardziej funkcjonalny sposób:
źródło
filter
imap
powinien umrzeć i zostać pochłonięty listami, a nie wyhodować więcej wariantów”.dict
inne typy mapowania, takie jakcollections.OrderedDict
lubcollections.defaultdict
To rozszerza się na odpowiedź Roberta , mającą zastosowanie do sytuacji, gdy wartości w dykcie nie są unikalne.
Implementacja jest ograniczona, ponieważ nie można użyć
reversed
dwa razy i odzyskać oryginał. To nie jest symetryczne jako takie. Jest testowany z Python 2.6. Oto przykład użycia tego, w jaki sposób drukuję wynikowy dykt.Jeśli wolisz użyć
set
niż alist
, a mogą istnieć nieuporządkowane aplikacje, dla których ma to sens, zamiastsetdefault(v, []).append(k)
używaćsetdefault(v, set()).add(k)
.źródło
revdict.setdefault(v, set()).add(k)
set
. Obowiązuje tutaj typ wewnętrzny. Co jeśli chcę znaleźć wszystkie klucze, których wartości nie są1
lub2
? Potem mogę po prostu zrobićd.keys() - inv_d[1] - inv_d[2]
(w Pythonie 3)Możemy również odwrócić słownik za pomocą duplikatów kluczy, używając
defaultdict
:Zobacz tutaj :
źródło
Na przykład masz następujący słownik:
I chcesz uzyskać to w takiej odwróconej formie:
Pierwsze rozwiązanie . Aby odwrócić pary klucz-wartość w słowniku, użyj
for
metody -loop:Drugie rozwiązanie . Użyj inwersji ze słownikiem :
Trzecie rozwiązanie . Użyj odwrócenia metody inwersji (polega na drugim rozwiązaniu):
źródło
dict
jest zarezerwowany i nie należy go używać do nazw zmiennychmy_map
jestdictio()
? Miałeś na myślidict()
?Połączenie rozumienia listy i słownika. Może obsługiwać duplikaty kluczy
źródło
Jeśli wartości nie są unikalne, a ty jesteś trochę hardkorowy:
Zwłaszcza w przypadku dużego nagrania zauważ, że to rozwiązanie jest o wiele mniej wydajne niż odpowiedź Python odwracający / odwracający mapowanie, ponieważ zapętla się
items()
wielokrotnie.źródło
-1
ponieważ nadal odpowiada na pytanie, tylko moja opinia.Oprócz innych funkcji sugerowanych powyżej, jeśli lubisz lambdas:
Możesz też zrobić to w ten sposób:
źródło
Myślę, że najlepszym sposobem na to jest zdefiniowanie klasy. Oto implementacja „słownika symetrycznego”:
Metody usuwania i iteracji są wystarczająco łatwe do wdrożenia, jeśli są potrzebne.
Ta implementacja jest znacznie wydajniejsza niż odwracanie całego słownika (który wydaje się być najpopularniejszym rozwiązaniem na tej stronie). Nie wspominając o tym, że możesz dodawać lub usuwać wartości z SymDict tyle, ile chcesz, a słownik odwrotny zawsze pozostanie ważny - nie jest to prawdą, jeśli po prostu raz odwrócisz cały słownik.
źródło
dictresize
, ale takie podejście zaprzecza Pythonowi na taką możliwość.To obsługuje nie unikalne wartości i zachowuje wiele z wyglądu unikalnej skrzynki.
Dla Pythona 3.x, wymienić
itervalues
zvalues
.źródło
Funkcja jest symetryczna dla wartości listy typów; Krotki są pokrywane do list podczas wykonywania reverse_dict (reverse_dict (słownik))
źródło
Ponieważ słowniki wymagają jednego unikalnego klucza w słowniku, w przeciwieństwie do wartości, musimy dołączyć odwrócone wartości do listy sortowania, która ma zostać uwzględniona w nowych określonych kluczach.
źródło
Szybkie funkcjonalne rozwiązanie dla map niebiotywnych (wartości nie unikalne):
Teoretycznie powinno to być szybsze niż dodawanie do zestawu (lub dołączanie do listy) jeden po drugim, jak w rozwiązaniu imperatywnym .
Niestety wartości muszą być sortowalne, sortowanie jest wymagane przez groupby.
źródło
n
elementy oryginalnego dyktanda, twoje podejście maO(n log n)
złożoność czasową z powodu potrzeby sortowania elementów tego dykta, podczas gdy naiwne imperatywne podejście maO(n)
złożoność czasową. Z tego co wiem, twoje podejście może być szybsze aż do absurdalnie dużychdict
w praktyce , ale z pewnością nie jest szybsze w teorii.Wypróbuj to dla Pythona 2.7 / 3.x
źródło
Zrobiłbym tak w Pythonie 2.
źródło
dict.items
(lubiteritems
w Pythonie 2) jest bardziej wydajne niż wyodrębnianie każdej wartości osobno podczas iteracji kluczy.Zapewni to wynik w postaci: {1: ['a', 'd'], 2: ['b'], 3: ['c']}
źródło
dict.items
(lubiteritems
w Pythonie 2) jest bardziej wydajne niż wyodrębnianie każdej wartości osobno podczas iteracji kluczy. Ponadto nie dodałeś żadnego wyjaśnienia do odpowiedzi, która powiela inne osoby.ten kod robi to tak:
źródło
Nie jest to coś zupełnie innego, tylko nieco przepisany przepis z książki kucharskiej. Jest dalej optymalizowany metodą przechowywania
setdefault
, zamiast za każdym razem, gdy przechodzi przez instancję:Zaprojektowany do pracy pod CPython 3.x, dla wersji 2.x
mapping.items()
zmapping.iteritems()
Na mojej maszynie działa trochę szybciej niż inne przykłady tutaj
źródło
dict
a następnie przekształcanie go w pożądaną klasę na końcu (zamiast zaczynać od klasy odpowiedniego typu) wydaje mi się, że powoduje tutaj całkowicie niemożliwe do uniknięcia uderzenie wydajności.Napisałem to za pomocą cyklu „for” i metody „.get ()” i zmieniłem nazwę „map” słownika na „map1”, ponieważ „map” jest funkcją.
źródło
Jeśli wartości nie są unikalne ORAZ może być skrótem (jeden wymiar):
I z rekurencją, jeśli chcesz kopać głębiej, to tylko jeden wymiar:
źródło
{"foo": "bar"}
się{'b': ['foo'], 'a': ['foo'], 'r': ['foo']}
i podnosi wyjątek jeśli wartośćmyDict
nie jest iterable. Nie jestem pewien, jakie zachowanie próbujesz tutaj zastosować, ale to, co faktycznie wdrożyłeś, jest czymś, czego nikt nie będzie chciał.