470 Stimmen

Teilmenge von Schlüssel-Wert-Paaren aus Wörterbuch extrahieren?

Ich habe ein großes Wörterbuch-Objekt, das mehrere Schlüssel-Wert-Paare (etwa 16) hat, aber ich bin nur an 3 von ihnen interessiert. Was ist der beste Weg (kürzeste/effizienteste/eleganteste), um das zu erreichen?

Das Beste, was ich weiß, ist:

bigdict = {'a':1,'b':2,....,'z':26} 
subdict = {'l':bigdict['l'], 'm':bigdict['m'], 'n':bigdict['n']}

Ich bin sicher, dass es einen eleganteren Weg als diesen gibt.

618voto

Mark Longair Punkte 412179

Sie könnten es versuchen:

dict((k, bigdict[k]) for k in ('l', 'm', 'n'))

... oder in Python 3 Python Versionen 2.7 oder höher (Dank an Fábio Diniz für den Hinweis darauf, dass es auch in 2.7 funktioniert) :

{k: bigdict[k] for k in ('l', 'm', 'n')}

Aktualisierung: Als Håvard S weist darauf hin, dass ich davon ausgehe, dass Sie wissen, dass die Schlüssel im Wörterbuch stehen werden - siehe seine Antwort wenn Sie nicht in der Lage sind, diese Vermutung anzustellen. Alternativ dazu, als timbo weist in den Kommentaren darauf hin, dass man einen Schlüssel, der in bigdict zur Abbildung auf None können Sie tun:

{k: bigdict.get(k, None) for k in ('l', 'm', 'n')}

Wenn Sie Python 3 verwenden, und Sie nur Schlüssel im neuen Diktat suchen, die auch im ursprünglichen Diktat vorhanden sind, können Sie diese Tatsache nutzen, um Objekte anzuzeigen und einige Mengenoperationen durchzuführen:

{k: bigdict[k] for k in bigdict.keys() & {'l', 'm', 'n'}}

13 Stimmen

{k: bigdict.get(k,None) for k in ('l', 'm', 'n')} behandelt die Situation, in der ein bestimmter Schlüssel im Quellwörterbuch fehlt, indem es den Schlüssel im neuen Diktat auf None setzt

0 Stimmen

Danke, @timbo - ich habe das auch zur Antwort hinzugefügt, ich hoffe, das ist OK

9 Stimmen

@MarkLongair Je nach Anwendungsfall könnte {k: bigdict[k] for k in ('l','m','n') if k in bigdict} besser sein, da es nur die Schlüssel speichert, die tatsächlich Werte haben.

153voto

Håvard S Punkte 22133

Zumindest ein bisschen kürzer:

wanted_keys = ['l', 'm', 'n'] # The keys you want
dict((k, bigdict[k]) for k in wanted_keys if k in bigdict)

12 Stimmen

+1 für das alternative Verhalten, einen Schlüssel auszuschließen, wenn er nicht in bigdict enthalten ist, anstatt ihn auf None zu setzen.

2 Stimmen

Alternativ dazu: dict((k,bigdict.get(k,defaultVal) for k in wanted_keys) wenn Sie alle Schlüssel haben müssen.

5 Stimmen

Diese Antwort ist mit einem "t" versehen.

38voto

Sklavit Punkte 1979

Ein kleiner Geschwindigkeitsvergleich für alle genannten Methoden:

AKTUALISIERT am 2020.07.13 (Dank an @user3780389): NUR für Schlüssel von bigdict.

 IPython 5.5.0 -- An enhanced Interactive Python.
Python 2.7.18 (default, Aug  8 2019, 00:00:00) 
[GCC 7.3.1 20180303 (Red Hat 7.3.1-5)] on linux2
import numpy.random as nprnd
  ...: keys = nprnd.randint(100000, size=10000)
  ...: bigdict = dict([(_, nprnd.rand()) for _ in range(100000)])
  ...: 
  ...: %timeit {key:bigdict[key] for key in keys}
  ...: %timeit dict((key, bigdict[key]) for key in keys)
  ...: %timeit dict(map(lambda k: (k, bigdict[k]), keys))
  ...: %timeit {key:bigdict[key] for key in set(keys) & set(bigdict.keys())}
  ...: %timeit dict(filter(lambda i:i[0] in keys, bigdict.items()))
  ...: %timeit {key:value for key, value in bigdict.items() if key in keys}
100 loops, best of 3: 2.36 ms per loop
100 loops, best of 3: 2.87 ms per loop
100 loops, best of 3: 3.65 ms per loop
100 loops, best of 3: 7.14 ms per loop
1 loop, best of 3: 577 ms per loop
1 loop, best of 3: 563 ms per loop

Wie zu erwarten war: Wörterbucherläuterungen sind die beste Option.

1 Stimmen

Die ersten 3 Operationen machen etwas anderes als die letzten beiden und führen zu einem Fehler, wenn key gibt es nicht in bigdict .

3 Stimmen

Schön. Vielleicht sollte man sie hinzufügen. {key:bigdict[key] for key in bigdict.keys() & keys} von der akzeptierte Lösung die den Filter erreicht und dabei (auf meinem Rechner) schneller ist als die erste von Ihnen aufgeführte Methode, die nicht filtert. In der Tat, {key:bigdict[key] for key in set(keys) & set(bigdict.keys())} scheint für diese sehr großen Schlüsselsätze noch schneller zu sein ...

0 Stimmen

@telchert Sie übersehen, dass in dem gebenden Geschwindigkeitsvergleich bigdict.keys() & keys keine Sets sind. Und bei expliziter Umwandlung in Mengen ist die akzeptierte Lösung nicht so schnell.

30voto

theheadofabroom Punkte 18431
interesting_keys = ('l', 'm', 'n')
subdict = {x: bigdict[x] for x in interesting_keys if x in bigdict}

0 Stimmen

@loutre wie wollen Sie sonst sicherstellen, dass Sie alle Daten für die angegebenen Schlüssel extrahieren?

1 Stimmen

Sry Ich habe einen Fehler gemacht. Ich dachte, Sie würden bei "bigdict" eine Schleife drehen. Mein Fehler. Ich lösche meinen Kommentar

18voto

Meow Punkte 1050

Bei dieser Antwort wird ein ähnliches Wörterbuchverständnis wie bei der ausgewählten Antwort verwendet, aber es wird nicht auf einen fehlenden Begriff verzichtet.

python 2 Version:

{k:v for k, v in bigDict.iteritems() if k in ('l', 'm', 'n')}

python 3 Version:

{k:v for k, v in bigDict.items() if k in ('l', 'm', 'n')}

5 Stimmen

...aber wenn das große Diktat RIESIG ist, wird es immer noch komplett durchlaufen (dies ist eine O(n)-Operation), während die Umkehrung nur 3 Elemente erfassen würde (jeweils eine O(1)-Operation).

1 Stimmen

Die Frage bezieht sich auf ein Wörterbuch mit nur 16 Schlüsseln

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