969 Stimmen

Schlüssel nach Wert im Wörterbuch abrufen

Ich habe eine Funktion entwickelt, die die Altersangaben in einer Dictionary und zeigt den passenden Namen an:

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 man vergleicht und das Alter findet, aber ich weiß nicht, wie man den Namen der Person anzeigt. Außerdem erhalte ich eine KeyError wegen der Zeile 5. Ich weiß, dass das nicht korrekt ist, aber ich finde nicht heraus, wie ich die Suche rückwärts durchführen kann.

0 Stimmen

1 Stimmen

Würden Sie ein Wort anhand seiner Definition in einem Wörterbuch finden? NEIN.

0 Stimmen

Sie können eine verschlossene Tür nicht öffnen. (Es sei denn, man bricht sie auf.)

4voto

Bishwas Mishra Punkte 1094

Nur meine Antwort in lambda y filter .

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

4voto

Ozkan Serttas Punkte 897

Ich habe versucht, so viele Lösungen wie möglich zu lesen, um doppelte Antworten zu vermeiden. Wenn Sie jedoch mit einem Wörterbuch arbeiten, dessen Werte in Listen enthalten sind, und wenn Sie Schlüssel abrufen möchten, die ein bestimmtes Element enthalten, können Sie dies 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 wollen wir Namen finden, die 24 in ihren Werten haben.

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

Dies würde auch mit mehreren Werten funktionieren.

4voto

formiaczek Punkte 385

Ist beantwortet, aber es könnte mit einer ausgefallenen 'map/reduce'-Nutzung gemacht werden, z.B.:

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

3voto

Corley Brigman Punkte 10223

Wurde bereits beantwortet, aber da mehrere Leute die Umkehrung des Wörterbuchs erwähnten, hier ist, wie man es in einer Zeile macht (unter der Annahme einer 1:1-Zuordnung) und einige verschiedene 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 glauben, dass es nicht 1:1 ist, können Sie immer noch 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 denken würde - bei einem "einfachen" Wörterbuch mit 100000 Einträgen war eine "schnelle" Suche (d.h. die Suche nach einem Wert, der am Anfang der Schlüssel stehen sollte) etwa 10x schneller als das Umkehren des gesamten Wörterbuchs, und eine "langsame" Suche (gegen Ende) etwa 4-5x schneller. Nach höchstens 10 Suchvorgängen hat sich das System also bereits 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

Ich habe auch einige interessante Ergebnisse mit ifilter erzielt. Theoretisch sollte ifilter schneller sein, da wir itervalues() verwenden können und möglicherweise nicht die gesamte Werteliste erstellen bzw. 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

Bei kleinen Offsets war sie also deutlich schneller als jede frühere Version (2,36 *u*S gegenüber einem Minimum von 1,48 *m*S bei früheren Versionen). Bei großen Offsets am Ende der Liste war sie jedoch deutlich langsamer (15,1 ms gegenüber denselben 1,48 ms). Die geringen Einsparungen am unteren Ende der Liste sind die Kosten am oberen Ende nicht wert, denke ich.

0 Stimmen

Ich möchte so sehr, dass dies (reversedict = defaultdict(list) reversedict[value].append(key) für Schlüssel, Wert in largedict.iteritems()] ) zu arbeiten, aber mit Python 2.7.3, erhalte ich Syntaxfehler auf das Wort "für

0 Stimmen

Ist es das, was Sie tatsächlich getippt haben? Es fehlt ein [ in den Text einfügen, wenn dies der Fall ist. Andernfalls sollten Sie sicherstellen, dass der Text auf zwei Zeilen steht, oder ein ; zwischen ihnen, wenn es nicht der Fall ist.

3voto

Dan Ahlquist Punkte 81

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

Die Definition eines Wörterbuchs ist analog zu der einer Abbildung in der Mathematik. In diesem Fall ist ein Diktat eine Abbildung von K (die Menge der Schlüssel) auf V (die Werte) - aber nicht umgekehrt. Wenn Sie ein Dict dereferenzieren, erwarten Sie, dass Sie genau einen Wert zurückbekommen. Es ist aber durchaus zulässig, dass verschiedene Schlüssel auf denselben Wert abgebildet werden, z. B.:

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

Wenn Sie einen Schlüssel anhand des entsprechenden Wertes nachschlagen, kehren Sie das Wörterbuch im Wesentlichen um. Aber ein Mapping ist nicht unbedingt invertierbar! In diesem Beispiel könnte die Frage nach dem Schlüssel, der v1 entspricht, k1 oder k3 ergeben. Sollten Sie beide zurückgeben? Oder nur den ersten gefundenen? Deshalb ist indexof() für Dictionaries undefiniert.

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

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X