web-dev-qa-db-de.com

Schlüssel nach Wert im Wörterbuch abrufen

Ich habe eine Funktion erstellt, die in einer Dictionary nach Alter sucht und 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 weiß, wie ich das Alter vergleichen und finden kann. Ich weiß einfach nicht, wie ich den Namen der Person anzeigen soll. Außerdem bekomme ich wegen der Zeile 5 eine KeyError. Ich weiß, es ist nicht korrekt, aber ich kann nicht herausfinden, wie ich es rückwärts suchen soll.

449
user998316

Da ist gar nichts. dict soll nicht auf diese Weise verwendet werden.

for name, age in dictionary.items():    # for name, age in dictionary.iteritems():  (for Python 2.x)
    if age == search_age:
        print(name)
403
Cat Plus Plus
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 trennt es die Werte des Wörterbuchs in einer Liste, ermittelt die Position des Werts, die Sie haben, und erhält den Schlüssel an dieser Position.

Weitere Informationen zu keys() und .values() in Python 3: Python: einfachste Möglichkeit, eine Liste von Werten von dict zu erhalten.

450
Stênio Elson

Wenn Sie sowohl den Namen als auch das Alter haben möchten, sollten Sie .items() verwenden, wodurch Sie (key, value)-Schlüssel erhalten:

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

Sie können den Tupel direkt in der for-Schleife in zwei separate Variablen auspacken und dann dem Alter entsprechen.

Sie sollten auch das Wörterbuch umkehren, wenn Sie normalerweise 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 mydict anstelle von list genannt, weil list der Name eines integrierten Typs ist und Sie diesen Namen nicht für andere Zwecke verwenden sollten.

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

[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)

dies gibt Ihnen nur None, wenn es niemanden mit diesem Alter gibt.

Wenn dict lang ist und Sie sich in Python 2 befinden, sollten Sie .iteritems() anstelle von .items() in Betracht ziehen, wie es Cat Plus Plus in seiner Antwort getan hat, da keine Kopie der Liste erforderlich ist.

202
agf

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

Hier sind einige Tests, die ich ausgefü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() bei 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

Das zeigt also, dass Methode 1 für ein kleines Diktier am schnellsten ist. Dies ist am wahrscheinlichsten, weil es die erste Übereinstimmung zurückgibt, im Gegensatz zu allen Übereinstimmungen wie Methode 2 (siehe Hinweis unten).


Interessanterweise bekomme ich bei einem Dict, das ich mit 2700 Einträgen durchgeführt habe, ziemlich unterschiedliche Ergebnisse (diesmal 10000 Mal):

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 viel schneller. Zeigt nur an, wie groß die Größe Ihres Diktats ist, welche Methode Sie wählen.

Anmerkungen: Methode 2 gibt eine Liste von all names zurück, wohingegen 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 im Speicher ablegt.

58
Patrick

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

erklärung: i.keys () und i.values ​​() geben zwei Listen mit Schlüssel bzw. Werten des Wörterbuchs zurück. Mit der Zip-Funktion können Listen zu einem Wörterbuch zusammengefügt werden.

warnung: Dies funktioniert nur, wenn die Werte hashierbar und eindeutig sind.

p = dict(Zip(i.values(),i.keys()))
38
fanny
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}
22
Jelen
lKey = [key for key, value in lDictionary.iteritems() if value == lValue][0]
19
faham

Den Schlüssel erhalten Sie mit den Methoden dict.keys() , dict.values() und list.index() , siehe Codebeispiele unten:

names_dict = {'george':16,'amber':19}
search_age = int(raw_input("Provide age"))
key = names_dict.keys()[names_dict.values().index(search_age)]
9
Andriy Ivaneyko

Hier ist meine Meinung zu diesem Problem. Ich habe gerade angefangen, Python zu lernen.

"Die für Anfänger verständliche" 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!
9
Deithrian

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

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

Ich fand das answer sehr effektiv, aber immer noch nicht sehr einfach für mich zu lesen.

Um es klarer zu machen, können Sie den Schlüssel und den Wert eines Wörterbuchs umkehren. Dies ist die Schlüsselwerte und die Werteschlüssel, wie man hier sieht.

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 dieses andere Antwort .

6
Rafael Valero

Verwenden Sie diesen One-Liner, um ein Wörterbuch umzukehren:

reversed_dictionary = dict(map(reversed, dictionary.items()))
6
johnaphun

In diesem Fall verwendet recover_key das Wörterbuch und den Wert, um es im Wörterbuch zu finden. Wir durchlaufen dann die Schlüssel im Wörterbuch und vergleichen 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
6
shishir

Verwenden Sie Pandas. Wie in William McKinneys "Python für die Datenanalyse" angegeben

Eine andere Möglichkeit, über eine Serie nachzudenken, ist eine festgelegte Länge dict, da es eine Zuordnung von Indexwerten zu Datenwerten ist. Es kann sein Wird in vielen Kontexten verwendet, in denen Sie möglicherweise ein Diktat verwenden.

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

Um Ihre Serie abzufragen, gehen Sie wie folgt vor:

lookup_list[lookup_list.values == 19]

Was bringt:

Out[1]: 
amber    19
dtype: int64

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

answer = lookup_list[lookup_list.values == 19].index
answer = pd.Index.tolist(answer)
6
Axel
get_key = lambda v, d: next(k for k in d if d[k] is v)
4
Brett
for name in mydict.keys():
    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
4
patrick

es wird beantwortet, aber es könnte mit einer ausgefallenen Verwendung von "Karten/Reduzieren" 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()))
4
formiaczek
def get_Value(dic,value):
    for name in dic:
        if dic[name] == value:
            del dic[name]
            return name
4
Raj Damani

Ich hoffe das könnte helfen ...

for key in list:
   if list[key] == search_value:
       return key
3
Nat

Es gibt keine einfache Möglichkeit, einen Schlüssel in einer Liste zu finden, indem der Wert nachgeschlagen wird. Wenn Sie jedoch den Wert kennen, der die Tasten durchläuft, können Sie die Werte im Wörterbuch anhand des Elements nachschlagen. Wenn D [Element], bei dem 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)
3
Ethan

Ich weiß, dass dies alt ist, aber Sie können alle Personen in der Liste mit Ihrem Suchalter anhand des Listenverständnisses leicht finden.

ages = {'george':16,'amber':19}
search = 16
print([name for (name, age) in ages.items() if age == search])
3
fr1eza

hier ist meine Meinung dazu. Dies ist gut für die Anzeige mehrerer Ergebnisse, 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... 

3
user3649211

Sie müssen ein Wörterbuch verwenden und das Wörterbuch umkehren. Sie benötigen also eine andere Datenstruktur. Wenn Sie sich in Python 3 befinden, verwenden Sie enum module, aber wenn Sie Python 2.7 verwenden, verwenden Sie enum34, der 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 
2
Hamid FzM

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
2
wzbozon

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 Diktier eine Zuordnung von K (der Menge von Schlüsseln) zu V (den Werten) - nicht jedoch 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 auf denselben Wert abgebildet werden, z.

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

Wenn Sie einen Schlüssel anhand des entsprechenden Wertes nachschlagen, invertieren Sie das Wörterbuch im Wesentlichen. Ein Mapping ist jedoch nicht unbedingt invertierbar! In diesem Beispiel könnte die Abfrage nach dem Schlüssel, der v1 entspricht, k1 oder k3 ergeben. Sollten Sie beide zurückgeben? Nur das erste gefunden? Deshalb ist indexof () für Wörterbücher undefiniert.

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.

2
Dan Ahlquist
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.

Für mehrere Vorkommen verwenden Sie:

keys = [filter( lambda x: dictionary[x] == k  , dictionary )]
1
Cesar

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

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

ihre Namen sind natürlich so abwegig, dass es so aussieht, als würde es ein Alter drucken, aber es druckt den Namen. Da Sie auf 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
1
Surest Texas
d= {'george':16,'amber':19}

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

Die Ausgabe lautet wie folgt:

-> prints george
1
Jeroen

wurde bereits beantwortet, aber da mehrere Leute das Wörterbuch rückgängig gemacht haben, können Sie dies in einer Zeile tun (1: 1-Mapping vorausgesetzt) ​​und einige verschiedene Perforationsdaten:

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 immer noch ein vernünftiges Reverse-Mapping 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 Sie denken - bei einem "direkten" 100000-Eintragswörterbuch eine "schnelle" Suche (dh Suche nach einem Wert, der früh in den Schlüsseln sein sollte) war etwa 10x schneller als das gesamte Wörterbuch rückgängig zu machen, und eine "langsame" Suche (gegen Ende) ca. 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 müssen. In der Praxis waren die Ergebnisse ... ungerade ...

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

Bei kleinen Offsets war es also wesentlich schneller als jede vorherige Version (2.36 * u * S im Vergleich zu einem Minimum von 1.48 * m * S in früheren Fällen). Bei großen Offsets am Ende der Liste war sie jedoch dramatisch langsamer (15,1 ms gegenüber den gleichen 1,48 ms). Die kleinen Einsparungen am unteren Ende sind die Kosten am oberen Ende nicht wert, imho. 

1
Corley Brigman

Ein einfacher Weg, dies zu tun, könnte sein:

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

Dies gibt eine Liste der Schlüssel mit dem Wert zurück, der search_age entspricht. Sie können "list == search_age" bei Bedarf auch durch eine andere Bedingungsanweisung ersetzen.

0
Meilin He

wir können die Key von dict erhalten durch:

def getKey(dict,value):
     return [key for key in dict.keys() if (dict[key] == value)]
0
Sakhri Houssem

Ich habe versucht, so viele Lösungen wie möglich zu lesen, um eine doppelte Antwort zu vermeiden. Wenn Sie jedoch an einem Wörterbuch arbeiten, welche Werte in Listen enthalten sind und wenn Sie Schlüssel mit einem bestimmten Element erhalten möchten, können Sie Folgendes tun:

d = {'Adams': [18, 29, 30],
     'Allen': [9, 27],
     'Anderson': [24, 26],
     'Bailey': [7, 30],
     'Baker': [31, 7, 10, 19],
     'Barnes': [22, 31, 10, 21],
     'Bell': [2, 24, 17, 26]}

Jetzt können wir Namen suchen, die 24 Werte enthalten.

for key in d.keys():    
    if 24 in d[key]:
        print(key)

Dies würde auch mit mehreren Werten funktionieren. 

0
cyber-math

Nur meine Antwort in lambda und filter.

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

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 [search_age] erstellt das umgekehrte Wörterbuch (wobei Werte Schlüssel sind und umgekehrt) . Sie könnten eine Hilfsmethode erstellen, die dieses umgekehrte Wörterbuch zwischenspeichert:

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

oder ganz allgemein eine Fabrik, die eine Nachschlagemethode 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]

so könntest du tun:

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

Beachten Sie, dass ich list in ages_by_name umbenannt habe, da es sich um einen vordefinierten Typ handelt.

0
eold