Schlüssel nach Wert im Wörterbuch abrufen

630

Ich habe eine Funktion erstellt, die das Alter in a nachschlägt Dictionaryund den passenden Namen anzeigt:

dictionary = {'george' : 16, 'amber' : 19}
search_age = raw_input("Provide age")
for age in dictionary.values():
    if age == search_age:
        name = dictionary[age]
        print name

Ich kann das Alter vergleichen und finden. Ich weiß nur nicht, wie ich den Namen der Person anzeigen soll. Außerdem erhalte ich eine KeyErrorwegen Zeile 5. Ich weiß, dass sie nicht korrekt ist, aber ich kann nicht herausfinden, wie ich sie rückwärts suchen lassen kann.

user998316
quelle
Verwandte: Ein Wörterbuch-Mapping
umkehren
Würden Sie ein Wort basierend auf seiner Definition in einem Wörterbuch finden? NEE.
Jossie Calderon vor

Antworten:

562

Da ist gar nichts. dictist nicht dazu gedacht, auf diese Weise verwendet zu werden.

dictionary = {'george': 16, 'amber': 19}
search_age = input("Provide age")
for name, age in dictionary.items():  # for name, age in dictionary.iteritems():  (for Python 2.x)
    if age == search_age:
        print(name)
Cat Plus Plus
quelle
137
In Python 3.x list.items()anstelle von list.iteritems()sollte verwendet werden
Yuriy Petrovskiy
63
Ich stimme nicht zu ... die Antwort von agf unten ist konstruktiver. Ein völlig vernünftiger Anwendungsfall ist nicht "unbeabsichtigt" (Listenverständnis passt sowieso zu einem solchen Anwendungsfall). A dictkann für mehrere Dinge zu unterschiedlichen Zeiten sein; Schlüssel und Werte haben natürlich eine klare Bedeutung, aber " dictElemente mit einem bestimmten Wert" ist eine durchaus vernünftige Anforderung. Die Empfehlung, eine Liste von Paaren zu verwenden, würde den Kontext verwerfen, dass ein Element eine ' Definition ' vom anderen ist, z. B. in Parameterlisten ...
Louis Maddox
1
Ich stimme dieser Antwort nicht zu. Die Tatsache, dass es sich um eine Möglichkeit handelt, wie in der Antwort von Stênio Elson gezeigt, bedeutet nicht, dass sie nicht als solche verwendet werden sollte. Überhaupt nicht hilfreich.
Tropicalrambler
Würden Sie ein Wort in einem Wörterbuch finden, das auf seiner Definition basiert? NEE. @ Tropicalrambler
Jossie Calderon vor
598
mydict = {'george': 16, 'amber': 19}
print mydict.keys()[mydict.values().index(16)]  # Prints george

Oder in Python 3.x:

mydict = {'george': 16, 'amber': 19}
print(list(mydict.keys())[list(mydict.values()).index(16)])  # Prints george

Grundsätzlich werden die Werte des Wörterbuchs in einer Liste getrennt, die Position des Werts ermittelt und der Schlüssel an dieser Position abgerufen.

Weitere Informationen zu keys()und .values()in Python 3: Wie kann ich eine Liste mit Werten aus dict abrufen?

Stênio Elson
quelle
23
Sieht gut aus, aber funktioniert es immer? Ich meine, erzeugen list.keys()und list.values()Funktionen Elemente in derselben Reihenfolge?
Iskorum
17
Ja, sie sind garantiert konsistent. Außerdem wird garantiert, dass sich die Reihenfolge nicht durch Iterationen ändert, solange das Wörterbuch nicht geändert wird.
Veedrac
8
Dies scheint eine gute Lösung zu sein, aber der Index hat nur einen Wert richtig angegeben. Wenn Sie also mehrere gleiche Werte haben, sollte er mehrere Schlüssel zurückgeben, oder?
James Sapam
12
@ArtOfWarfare docs.python.org/3/library/stdtypes.html#dict-views , "Wenn Schlüssel-, Werte- und Elementansichten ohne dazwischenliegende Änderungen am Wörterbuch wiederholt werden, entspricht die Reihenfolge der Elemente direkt."
Veedrac
5
@sinekonata: Es führt immer noch eine teure Schleife unter der Haube durch; Die Schleife ist nur in der indexMethode versteckt .
user2357112 unterstützt Monica
252

Wenn Sie sowohl den Namen als auch das Alter möchten , sollten .items()Sie (key, value)Folgendes verwenden, um wichtige Tupel zu erhalten:

for name, age in mydict.items():
    if age == search_age:
        print name

Sie können das Tupel direkt in der forSchleife in zwei separate Variablen entpacken und dann dem Alter anpassen.

Sie sollten auch in Betracht ziehen, das Wörterbuch umzukehren, wenn Sie im Allgemeinen nach Alter suchen und keine zwei Personen das gleiche Alter haben:

{16: 'george', 19: 'amber'}

So können Sie den Namen für ein Alter nachschlagen, indem Sie einfach tun

mydict[search_age]

Ich habe es Aufruf mydictstatt , listda listist der Name einer eingebauten Typ, und Sie sollten diesen Namen nicht für etwas anderes verwenden.

Sie können sogar eine Liste aller Personen mit einem bestimmten Alter in einer Zeile abrufen:

[name for name, age in mydict.items() if age == search_age]

oder wenn es nur eine Person mit jedem Alter gibt:

next((name for name, age in mydict.items() if age == search_age), None)

Das gibt dir nur, Nonewenn es niemanden in diesem Alter gibt.

Wenn das dictlang ist und Sie Python 2 verwenden, sollten Sie die Verwendung .iteritems()anstelle von .items()Cat Plus Plus in seiner Antwort in Betracht ziehen , da keine Kopie der Liste erstellt werden muss.

agf
quelle
9
Richtig, aber wenn Sie eine lineare Suche durchführen möchten, können Sie die Suche auch durch dicteine Liste von Paaren ersetzen .
Fred Foo
9
Es sei denn, Ihre übliche Aktion besteht darin, nach Namen zu suchen. In diesem Fall dictist a sinnvoll.
Agf
2
Es scheint merkwürdig anzunehmen, dass es in jedem Alter nur eine Person gibt, während es für jede Person völlig logisch ist, ein einziges Alter zu haben.
Dannid
@Dannid Ja, aber das Problem kann leicht verallgemeinert werden. Sie könnten beispielsweise eine Nachschlagetabelle mit eindeutigen Schlüsseln und den entsprechenden eindeutigen Werten erstellen. Sie können dann die Dinge symmetrisch value --> keykey --> value
nachschlagen
67

Ich dachte, es wäre interessant, darauf hinzuweisen, welche Methoden in welchem ​​Szenario am schnellsten sind:

Hier sind einige Tests, die ich durchgeführt habe (auf einem 2012 MacBook Pro)

>>> def method1(list,search_age):
...     for name,age in list.iteritems():
...             if age == search_age:
...                     return name
... 
>>> def method2(list,search_age):
...     return [name for name,age in list.iteritems() if age == search_age]
... 
>>> def method3(list,search_age):
...     return list.keys()[list.values().index(search_age)]

Ergebnisse von profile.run()jeder Methode 100000 mal:

Methode 1:

>>> profile.run("for i in range(0,100000): method1(list,16)")
     200004 function calls in 1.173 seconds

Methode 2:

>>> profile.run("for i in range(0,100000): method2(list,16)")
     200004 function calls in 1.222 seconds

Methode 3:

>>> profile.run("for i in range(0,100000): method3(list,16)")
     400004 function calls in 2.125 seconds

Dies zeigt also, dass für ein kleines Diktat Methode 1 am schnellsten ist. Dies ist höchstwahrscheinlich darauf zurückzuführen, dass die erste Übereinstimmung zurückgegeben wird, im Gegensatz zu allen Übereinstimmungen wie bei Methode 2 (siehe Hinweis unten).


Interessanterweise erhalte ich bei der Durchführung der gleichen Tests für ein Diktat mit 2700 Einträgen ganz unterschiedliche Ergebnisse (diesmal 10000 Mal ausgeführt):

Methode 1:

>>> profile.run("for i in range(0,10000): method1(UIC_CRS,'7088380')")
     20004 function calls in 2.928 seconds

Methode 2:

>>> profile.run("for i in range(0,10000): method2(UIC_CRS,'7088380')")
     20004 function calls in 3.872 seconds

Methode 3:

>>> profile.run("for i in range(0,10000): method3(UIC_CRS,'7088380')")
     40004 function calls in 1.176 seconds

Hier ist Methode 3 also viel schneller. Nur um zu zeigen, die Größe Ihres Diktats beeinflusst, welche Methode Sie wählen.

Anmerkungen: Methode 2 gibt eine Liste aller Namen zurück, während Methode 1 und 3 nur die erste Übereinstimmung zurückgeben. Ich habe die Speichernutzung nicht berücksichtigt. Ich bin nicht sicher, ob Methode 3 zwei zusätzliche Listen (Schlüssel () und Werte ()) erstellt und diese im Speicher speichert.

Patrick
quelle
6
Nur ein Update: Es scheint, dass dict.values ​​() und dict.keys () beide Listen zurückgeben, die auf die Objekte aus dem ursprünglichen Diktat verweisen. Daher verwendet Methode 3 auch am wenigsten Speicher (es werden nur zwei Thin-List-Objekte erstellt die den Inhalt der Diktate einschließen, während die anderen Iteratorelemente erstellen
Patrick
Ich wollte es nur selbst messen, nach unten scrollen, da hast du es. Vielen Dank! Technisch gesehen macht Methode 2, wie Sie bereits betont haben, nicht genau das Gleiche wie 1 und 3, da alle Übereinstimmungen zurückgegeben werden. Es wäre schön, die Ergebnisse für zB return next ([..]) zu sehen.
BluBb_mADe
Ein weiterer wichtiger Hinweis ist die Python-Version. Ich weiß, dass einige Versionen Methoden effizienter implementieren als andere.
ArtOfWarfare
@Patrick: Alle Methoden verwenden direkte Verweise auf die Werte und Schlüssel, es gibt keinen Speichervorteil. Außer in Python 3 .keys()und " .values()Return Dictionary Views", die leicht sind.
Martijn Pieters
53

einzeilige Version: (i ist ein altes Wörterbuch, p ist ein umgekehrtes Wörterbuch)

Erläuterung: i.keys()und i.values()gibt zwei Listen mit Schlüsseln bzw. Werten des Wörterbuchs zurück. Die Zip-Funktion bietet die Möglichkeit, Listen zu verknüpfen, um ein Wörterbuch zu erstellen.

p = dict(zip(i.values(),i.keys()))

Warnung: Dies funktioniert nur, wenn die Werte hashbar und eindeutig sind.

Fanny
quelle
Ja, das wird funktionieren: stackoverflow.com/questions/835092/…
The Unfun Cat
17
... und wenn es keine doppelten Werte gibt.
Ely
3
Wunderschönen. In Bezug auf den obigen Kommentar funktioniert dies natürlich nur, wenn keine doppelten Werte vorhanden sind. Bei der Frage, mit der dieser Thread gestartet wurde, wird jedoch davon ausgegangen, dass wir eine Eins-zu-Eins-Funktion haben. Angesichts dieser Annahme ist dies die eleganteste Antwort bei weitem.
John Strong
1
Erweitern von Hash-Werten: Wenn Ihre Werte Listen / Sets sind, konvertieren Sie sie in Tupel, damit dies funktioniert (sie müssen immer noch eindeutig sein).
Myon
28
a = {'a':1,'b':2,'c':3}
{v:k for k, v in a.items()}[1]

oder besser

{k:v for k, v in a.items() if v == 1}
Jelen
quelle
5
Was ist, wenn es einen anderen Schlüssel gibt, der den gleichen Wert wie a enthält? Kann pythonisch sein. Aber keine gute Idee.
7H3 IN5ID3R
Guter Punkt, ich habe eine Lösung hinzugefügt, die mit nicht eindeutigen Werten funktioniert
Jelen
24
key = next((k for k in my_dict if my_dict[k] == val), None)
Faham
quelle
Kann ich in dieser Zeile auch ein "Sonst" haben? Für den Fall, dass mein Wert nicht in den diktierten Werten liegt
Srishti Gupta
lKey = [k for k, v in lDictionary.iteritems() if v == lValue][0] or 'else-key'
Faham
14

Versuchen Sie diesen Einzeiler, um ein Wörterbuch umzukehren:

reversed_dictionary = dict(map(reversed, dictionary.items()))
Johnaphun
quelle
1
Dies hat bei meinem Verschlüsselungs- und Entschlüsselungsprogramm hervorragend funktioniert, danke!
Christian R
Quelle
pfabri
13

Ich fand diese Antwort sehr effektiv, aber für mich nicht leicht zu lesen.

Zur Verdeutlichung können Sie den Schlüssel und den Wert eines Wörterbuchs invertieren. Dies macht die Schlüsselwerte und die Werteschlüssel, wie hier zu sehen .

mydict = {'george':16,'amber':19}
res = dict((v,k) for k,v in mydict.iteritems())
print(res[16]) # Prints george

oder

mydict = {'george':16,'amber':19}
dict((v,k) for k,v in mydict.iteritems())[16]

Das ist im Wesentlichen das gleiche wie diese andere Antwort .

Rafael Valero
quelle
12

Wenn Sie den Schlüssel anhand des Werts suchen möchten, können Sie mithilfe eines Wörterbuchverständnisses ein Suchwörterbuch erstellen und dann den Schlüssel anhand des Werts ermitteln.

lookup = {value: key for key, value in self.data}
lookup[value]
Safia Abdalla
quelle
11

Sie können Schlüssel mit Hilfe bekommen dict.keys(), dict.values()und list.index()Methoden finden Sie Codebeispiele unter:

names_dict = {'george':16,'amber':19}
search_age = int(raw_input("Provide age"))
key = names_dict.keys()[names_dict.values().index(search_age)]
Andriy Ivaneyko
quelle
2
Sie nicht definiert verwenden search_agevar auf nächste Zeile ... Vielleicht sollten Sie ersetzen valuemit search_age?
Andersson
2
Ich erhalte die folgende Fehlermeldung: Das Objekt 'dict_values' hat kein Attribut 'index'
Blue_Elephant
@Blue_Elephant Könnten Sie bitte ein Code-Snippet bereitstellen, bei dem Sie einen Fehler und eine Python-Version haben (auch ein Ausdruck von type(dict_values)wäre nützlich)?
Andriy Ivaneyko
9

Hier ist meine Sicht auf dieses Problem. :) Ich habe gerade angefangen, Python zu lernen, also nenne ich das:

"Das Verständnis für Anfänger" -Lösung.

#Code without comments.

list1 = {'george':16,'amber':19, 'Garry':19}
search_age = raw_input("Provide age: ")
print
search_age = int(search_age)

listByAge = {}

for name, age in list1.items():
    if age == search_age:
        age = str(age)
        results = name + " " +age
        print results

        age2 = int(age)
        listByAge[name] = listByAge.get(name,0)+age2

print
print listByAge

.

#Code with comments.
#I've added another name with the same age to the list.
list1 = {'george':16,'amber':19, 'Garry':19}
#Original code.
search_age = raw_input("Provide age: ")
print
#Because raw_input gives a string, we need to convert it to int,
#so we can search the dictionary list with it.
search_age = int(search_age)

#Here we define another empty dictionary, to store the results in a more 
#permanent way.
listByAge = {}

#We use double variable iteration, so we get both the name and age 
#on each run of the loop.
for name, age in list1.items():
    #Here we check if the User Defined age = the age parameter 
    #for this run of the loop.
    if age == search_age:
        #Here we convert Age back to string, because we will concatenate it 
        #with the person's name. 
        age = str(age)
        #Here we concatenate.
        results = name + " " +age
        #If you want just the names and ages displayed you can delete
        #the code after "print results". If you want them stored, don't...
        print results

        #Here we create a second variable that uses the value of
        #the age for the current person in the list.
        #For example if "Anna" is "10", age2 = 10,
        #integer value which we can use in addition.
        age2 = int(age)
        #Here we use the method that checks or creates values in dictionaries.
        #We create a new entry for each name that matches the User Defined Age
        #with default value of 0, and then we add the value from age2.
        listByAge[name] = listByAge.get(name,0)+age2

#Here we print the new dictionary with the users with User Defined Age.
print
print listByAge

.

#Results
Running: *\test.py (Thu Jun 06 05:10:02 2013)

Provide age: 19

amber 19
Garry 19

{'amber': 19, 'Garry': 19}

Execution Successful!
Deithrian
quelle
9
get_key = lambda v, d: next(k for k in d if d[k] is v)
Brett
quelle
Schöner Einzeiler. Allerdings issollte nur verwendet werden , für die Gleichstellung Prüfung von Singletons ( None, True, Falseetc.). Die Tatsache, dass CPython String-Literale wiederverwendet (und dies auch a = 'foobar'; a is 'foobar'ist True), ist ein Implementierungsdetail und sollte nicht als verlässlich angesehen werden.
piit79
1
Und noch ein Kommentar: get_keyWird ausgelöst, StopIterationwenn der Wert nicht im Wörterbuch vorhanden ist. Es ist besser, ihn zu verwenden, next(..., None)der zurückgibt, Nonewenn der Wert nicht gefunden wird.
piit79
Eine geringfügige Änderung funktioniert, wenn das Wörterbuch keine einzelnen Elemente enthält, sondern get_first_key = lambda v, d: next((k for k in d if (v in d[k] is not None)), None)
Supernova
7

Erwägen Sie die Verwendung von Pandas. Wie in William McKinneys "Python for Data Analysis" angegeben

Eine andere Möglichkeit, sich eine Serie vorzustellen, ist ein geordnetes Diktat mit fester Länge, da es sich um eine Zuordnung von Indexwerten zu Datenwerten handelt. Es kann in vielen Kontexten verwendet werden, in denen Sie möglicherweise ein Diktat verwenden.

import pandas as pd
list = {'george':16,'amber':19}
lookup_list = pd.Series(list)

Gehen Sie wie folgt vor, um Ihre Serien abzufragen:

lookup_list[lookup_list.values == 19]

Welche Ausbeuten:

Out[1]: 
amber    19
dtype: int64

Wenn Sie mit der Ausgabe etwas anderes tun müssen, kann es nützlich sein, die Antwort in eine Liste umzuwandeln:

answer = lookup_list[lookup_list.values == 19].index
answer = pd.Index.tolist(answer)
Axel
quelle
Er ist der Schöpfer von Pandas. Er ist jedoch allgemein als Wes bekannt.
Axel
6

Hier benötigt recovery_key Wörterbuch und Wert, um im Wörterbuch zu finden. Wir durchlaufen dann die Schlüssel im Wörterbuch und vergleichen sie mit dem Wert und geben diesen bestimmten Schlüssel zurück.

def recover_key(dicty,value):
    for a_key in dicty.keys():
        if (dicty[a_key] == value):
            return a_key
Shishir
quelle
4
for name in mydict:
    if mydict[name] == search_age:
        print(name) 
        #or do something else with it. 
        #if in a function append to a temporary list, 
        #then after the loop return the list
Patrick
quelle
1
Die Verwendung einer for-Schleife und eines Anhängens ist viel langsamer als ein Listenverständnis und auch länger.
Alexpinho98
4

wir können das Keyvon bekommen dictdurch:

def getKey(dct,value):
     return [key for key in dct if (dct[key] == value)]
Sakhri Houssem
quelle
3

Es wird beantwortet, aber es könnte mit einer ausgefallenen "Map / Reduce" -Verwendung durchgeführt werden, z.

def find_key(value, dictionary):
    return reduce(lambda x, y: x if x is not None else y,
                  map(lambda x: x[0] if x[1] == value else None, 
                      dictionary.iteritems()))
formiaczek
quelle
3

Cat Plus Plus erwähnte, dass ein Wörterbuch nicht so verwendet werden soll. Hier ist der Grund:

Die Definition eines Wörterbuchs entspricht der eines Mappings in der Mathematik. In diesem Fall ist ein Diktat eine Zuordnung von K (dem Satz von Schlüsseln) zu V (den Werten) - aber nicht umgekehrt. Wenn Sie ein Diktat dereferenzieren, erwarten Sie, dass genau ein Wert zurückgegeben wird. Es ist jedoch völlig legal, dass verschiedene Schlüssel demselben Wert zugeordnet werden, z.

d = { k1 : v1, k2 : v2, k3 : v1}

Wenn Sie einen Schlüssel anhand seines entsprechenden Werts nachschlagen, invertieren Sie im Wesentlichen das Wörterbuch. Ein Mapping ist aber nicht unbedingt invertierbar! In diesem Beispiel könnte die Frage nach dem Schlüssel für v1 k1 oder k3 ergeben. Sollten Sie beide zurückgeben? Nur der erste gefunden? Aus diesem Grund ist indexof () für Wörterbücher nicht definiert.

Wenn Sie Ihre Daten kennen, können Sie dies tun. Eine API kann jedoch nicht davon ausgehen, dass ein beliebiges Wörterbuch invertierbar ist, weshalb eine solche Operation fehlt.

Dan Ahlquist
quelle
3

Hier ist meine Meinung dazu. Dies ist gut, um mehrere Ergebnisse anzuzeigen, falls Sie eines benötigen. Also habe ich auch die Liste hinzugefügt

myList = {'george':16,'amber':19, 'rachel':19, 
           'david':15 }                         #Setting the dictionary
result=[]                                       #Making ready of the result list
search_age = int(input('Enter age '))

for keywords in myList.keys():
    if myList[keywords] ==search_age:
    result.append(keywords)                    #This part, we are making list of results

for res in result:                             #We are now printing the results
    print(res)

Und das ist es...

user3649211
quelle
3
d= {'george':16,'amber':19}

dict((v,k) for k,v in d.items()).get(16)

Die Ausgabe ist wie folgt:

-> prints george
Jeroen
quelle
[k für k, v in d.items () wenn v == 16]
auro
3

Es gibt keine einfache Möglichkeit, einen Schlüssel in einer Liste zu finden, indem Sie den Wert nachschlagen. Wenn Sie jedoch den Wert kennen und die Schlüssel durchlaufen, können Sie die Werte im Wörterbuch nach dem Element suchen. Wenn D [Element], wobei D ein Wörterbuchobjekt ist, dem Schlüssel entspricht, den Sie suchen möchten, können Sie Code ausführen.

D = {'Ali': 20, 'Marina': 12, 'George':16}
age = int(input('enter age:\t'))  
for element in D.keys():
    if D[element] == age:
        print(element)
Ethan
quelle
3

Sie müssen ein Wörterbuch verwenden und dieses Wörterbuch umkehren. Dies bedeutet, dass Sie eine andere Datenstruktur benötigen. Wenn Sie sich in Python 3 befinden, verwenden Sie das enumModul. Wenn Sie jedoch Python 2.7 verwenden , verwenden Sie das Modul, enum34das für Python 2 zurückportiert ist.

Beispiel:

from enum import Enum

class Color(Enum): 
    red = 1 
    green = 2 
    blue = 3

>>> print(Color.red) 
Color.red

>>> print(repr(Color.red)) 
<color.red: 1=""> 

>>> type(Color.red) 
<enum 'color'=""> 
>>> isinstance(Color.green, Color) 
True 

>>> member = Color.red 
>>> member.name 
'red' 
>>> member.value 
1 
hamidfzm
quelle
2
def get_Value(dic,value):
    for name in dic:
        if dic[name] == value:
            del dic[name]
            return name
Raj Damani
quelle
1
Warum den Schlüssel aus dem Wörterbuch entfernen? das beantwortet die Frage nicht
Jean-François Fabre
2

Nur meine Antwort in lambdaund filter.

filter( lambda x, dictionary=dictionary, search_age=int(search_age): dictionary[x] == search_age  , dictionary )
Bishwas Mishra
quelle
1

wurde bereits beantwortet, aber da mehrere Leute das Umkehren des Wörterbuchs erwähnt haben, gehen Sie wie folgt in einer Zeile vor (unter der Annahme einer 1: 1-Zuordnung) und einigen verschiedenen Perf-Daten:

Python 2.6:

reversedict = dict([(value, key) for key, value in mydict.iteritems()])

2.7+:

reversedict = {value:key for key, value in mydict.iteritems()}

Wenn Sie der Meinung sind, dass es nicht 1: 1 ist, können Sie dennoch eine vernünftige umgekehrte Zuordnung mit ein paar Zeilen erstellen:

reversedict = defaultdict(list)
[reversedict[value].append(key) for key, value in mydict.iteritems()]

Wie langsam ist das? Langsamer als eine einfache Suche, aber nicht annähernd so langsam wie man denkt - bei einem "geraden" Wörterbuch mit 100000 Einträgen eine "schnelle" Suche (dh Suche nach einem Wert, der früh in den Tasten sein sollte) war ungefähr 10x schneller als das Umkehren des gesamten Wörterbuchs und eine "langsame" Suche (gegen Ende) ungefähr 4-5x schneller. Nach höchstens 10 Suchvorgängen hat es sich also bezahlt gemacht.

Die zweite Version (mit Listen pro Element) dauert etwa 2,5-mal so lange wie die einfache Version.

largedict = dict((x,x) for x in range(100000))

# Should be slow, has to search 90000 entries before it finds it
In [26]: %timeit largedict.keys()[largedict.values().index(90000)]
100 loops, best of 3: 4.81 ms per loop

# Should be fast, has to only search 9 entries to find it. 
In [27]: %timeit largedict.keys()[largedict.values().index(9)]
100 loops, best of 3: 2.94 ms per loop

# How about using iterkeys() instead of keys()?
# These are faster, because you don't have to create the entire keys array.
# You DO have to create the entire values array - more on that later.

In [31]: %timeit islice(largedict.iterkeys(), largedict.values().index(90000))
100 loops, best of 3: 3.38 ms per loop

In [32]: %timeit islice(largedict.iterkeys(), largedict.values().index(9))
1000 loops, best of 3: 1.48 ms per loop

In [24]: %timeit reversedict = dict([(value, key) for key, value in largedict.iteritems()])
10 loops, best of 3: 22.9 ms per loop

In [23]: %%timeit
....: reversedict = defaultdict(list)
....: [reversedict[value].append(key) for key, value in largedict.iteritems()]
....:
10 loops, best of 3: 53.6 ms per loop

Hatte auch einige interessante Ergebnisse mit ifilter. Theoretisch sollte ifilter schneller sein, da wir itervalues ​​() verwenden können und möglicherweise nicht die gesamte Werteliste erstellen / durchgehen müssen. In der Praxis waren die Ergebnisse ... seltsam ...

In [72]: %%timeit
....: myf = ifilter(lambda x: x[1] == 90000, largedict.iteritems())
....: myf.next()[0]
....:
100 loops, best of 3: 15.1 ms per loop

In [73]: %%timeit
....: myf = ifilter(lambda x: x[1] == 9, largedict.iteritems())
....: myf.next()[0]
....:
100000 loops, best of 3: 2.36 us per loop

Für kleine Offsets war es also dramatisch schneller als jede frühere Version (2,36 * u * S gegenüber einem Minimum von 1,48 * m * S für frühere Fälle). Bei großen Offsets gegen Ende der Liste war sie jedoch dramatisch langsamer (15,1 ms gegenüber denselben 1,48 ms). Die kleinen Einsparungen am unteren Ende sind die Kosten am oberen Ende nicht wert, imho.

Corley Brigman
quelle
Ich möchte so sehr, dass dies (reversedict = defaultdict (Liste) reversedict [Wert] .append (Schlüssel) für Schlüssel, Wert in largedict.iteritems ()]) funktioniert, aber mit Python 2.7.3 erhalte ich einen Syntaxfehler für das Wort 'für'
slashdottir
hast du das tatsächlich getippt? Sie vermissen ein [darin, wenn es ist. Stellen Sie andernfalls sicher, dass es sich um zwei Zeilen handelt, oder setzen Sie eine ;dazwischen, wenn dies nicht der Fall ist.
Corley Brigman
1

Manchmal kann int () benötigt werden:

titleDic = {'Фильмы':1, 'Музыка':2}

def categoryTitleForNumber(self, num):
    search_title = ''
    for title, titleNum in self.titleDic.items():
        if int(titleNum) == int(num):
            search_title = title
    return search_title
Denis Kutlubaev
quelle
1

Hier ist eine Lösung, die sowohl in Python 2 als auch in Python 3 funktioniert:

dict((v, k) for k, v in list.items())[search_age]

Der Teil bis erstellt [search_age]das umgekehrte Wörterbuch (wobei Werte Schlüssel sind und umgekehrt). Sie können eine Hilfsmethode erstellen, die dieses umgekehrte Wörterbuch wie folgt zwischenspeichert:

def find_name(age, _rev_lookup=dict((v, k) for k, v in ages_by_name.items())):
    return _rev_lookup[age]

oder noch allgemeiner eine Fabrik, die eine Methode zur Suche nach Namen nach Alter für eine oder mehrere Ihrer Listen erstellt

def create_name_finder(ages_by_name):
    names_by_age = dict((v, k) for k, v in ages_by_name.items())
    def find_name(age):
      return names_by_age[age]

Sie könnten also Folgendes tun:

find_teen_by_age = create_name_finder({'george':16,'amber':19})
...
find_teen_by_age(search_age)

Beachten Sie, dass ich umbenannt habe list, ages_by_nameda ersterer ein vordefinierter Typ ist.

eold
quelle
1

So greifen Sie auf das Wörterbuch zu, um das zu tun, was Sie wollen:

list = {'george': 16, 'amber': 19}
search_age = raw_input("Provide age")
for age in list:
    if list[age] == search_age:
        print age

Natürlich sind Ihre Namen so falsch, dass es so aussieht, als würde es ein Alter drucken, aber es druckt den Namen. Da Sie über den Namen zugreifen, wird es verständlicher, wenn Sie schreiben:

list = {'george': 16, 'amber': 19}
search_age = raw_input("Provide age")
for name in list:
    if list[name] == search_age:
        print name

Besser noch:

people = {'george': {'age': 16}, 'amber': {'age': 19}}
search_age = raw_input("Provide age")
for name in people:
    if people[name]['age'] == search_age:
        print name

quelle
1
dictionary = {'george' : 16, 'amber' : 19}
search_age = raw_input("Provide age")
key = [filter( lambda x: dictionary[x] == k  , dictionary ),[None]][0] 
# key = None from [None] which is a safeguard for not found.

Verwenden Sie für mehrere Vorkommen:

keys = [filter( lambda x: dictionary[x] == k  , dictionary )]
Cesar
quelle
*** NameError: global name 'dictionary' is not defined
Bishwas Mishra
filter( lambda x, dictionary=dictionary, search_age=int(search_age): dictionary[x] == search_age , dictionary )
Bishwas Mishra