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.
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)
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.
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.
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.
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()))
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}
lKey = [key for key, value in lDictionary.iteritems() if value == lValue][0]
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)]
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!
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]
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 .
Verwenden Sie diesen One-Liner, um ein Wörterbuch umzukehren:
reversed_dictionary = dict(map(reversed, dictionary.items()))
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
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)
get_key = lambda v, d: next(k for k in d if d[k] is v)
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
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()))
def get_Value(dic,value):
for name in dic:
if dic[name] == value:
del dic[name]
return name
Ich hoffe das könnte helfen ...
for key in list:
if list[key] == search_value:
return key
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)
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])
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...
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
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
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.
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 )]
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
d= {'george':16,'amber':19}
dict((v,k) for k,v in d.items()).get(16)
Die Ausgabe lautet wie folgt:
-> prints george
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.
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.
wir können die Key
von dict
erhalten durch:
def getKey(dict,value):
return [key for key in dict.keys() if (dict[key] == value)]
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.
Nur meine Antwort in lambda
und filter
.
filter( lambda x, dictionary=dictionary, search_age=int(search_age): dictionary[x] == search_age , dictionary )
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.