793 Stimmen

Diktat so filtern, dass es nur bestimmte Schlüssel enthält?

Ich habe eine dict die eine ganze Reihe von Einträgen enthält. Ich interessiere mich nur für einige wenige von ihnen. Gibt es eine einfache Möglichkeit, alle anderen auszusortieren?

0 Stimmen

Es ist hilfreich zu sagen, welche Art von Schlüsseln (Ganzzahlen? Zeichenketten? Daten? beliebige Objekte?) und somit, ob es eine einfache (String, Regex, Liste Mitgliedschaft oder numerische Ungleichheit) Test zu überprüfen, welche Schlüssel sind in oder out. Oder müssen wir eine beliebige Funktion(en) aufrufen, um das festzustellen.

1 Stimmen

@smci String-Schlüssel. Ich glaube nicht, dass es mir überhaupt in den Sinn gekommen ist, etwas anderes zu verwenden; ich habe so lange in JS und PHP programmiert...

980voto

Konstruktion eines neuen Diktats:

dict_you_want = { your_key: old_dict[your_key] for your_key in your_keys }

Verwendet das Wörterbuchverständnis.

Wenn Sie eine Version verwenden, in der diese fehlen (z.B. Python 2.6 und früher), machen Sie es dict((your_key, old_dict[your_key]) for ...) . Es ist dasselbe, nur hässlicher.

Beachten Sie, dass diese Version im Gegensatz zur Version von jnnnnn eine stabile Leistung (hängt nur von der Anzahl der your_keys ab) für old_dict s in jeder Größe. Sowohl in Bezug auf die Geschwindigkeit als auch auf den Speicher. Da es sich um einen Generatorausdruck handelt, wird jeweils nur ein Element verarbeitet, und es werden nicht alle Elemente von old_dict durchsucht.

Entfernen Sie alles an Ort und Stelle:

unwanted = set(keys) - set(your_dict)
for unwanted_key in unwanted: del your_dict[unwanted_key]

9 Stimmen

"Verwendet Wörterbuchverständnis, wenn Sie eine Version verwenden, in der dies fehlt" == Version <= 2.6

38 Stimmen

Wirft einen KeyError, wenn einer der Dateischlüssel nicht in old_dict vorhanden ist. Ich würde vorschlagen {k:d[k] for k in filter if k in d}

7 Stimmen

@PeterGibson Ja, wenn das Teil der Anforderungen ist, müssen Sie etwas darüber. Ob die Schlüssel stillschweigend weggelassen werden, ein Standardwert hinzugefügt wird oder etwas anderes, hängt davon ab, was Sie tun; es gibt viele Anwendungsfälle, in denen Ihr Ansatz falsch ist. Es gibt auch viele Fälle, in denen ein fehlender Schlüssel in old_dict deutet auf einen Fehler an anderer Stelle hin, und in diesem Fall ziehe ich einen Fehler einem stillschweigend falschen Ergebnis vor.

264voto

ransford Punkte 2347

Ein etwas eleganteres Diktatverständnis:

foodict = {k: v for k, v in mydict.items() if k.startswith('foo')}

1 Stimmen

Hochgestuft. Ich habe darüber nachgedacht, eine Antwort ähnlich dieser hinzuzufügen. Nur aus Neugierde, warum {k:v for k,v in dict.items() ...} und nicht {k:dict[k] for k in dict ...} Gibt es einen Leistungsunterschied?

9 Stimmen

Ich habe meine eigene Frage beantwortet. Die Methode {k:dict[k] for k in dict ...} ist zumindest in Python 2.7.6 bei einem Wörterbuch mit 26 Einträgen etwa 20-25% schneller (timeit(..., setup="d = {chr(x+97):x+1 for x in range(26)}"), je nachdem, wie viele Einträge herausgefiltert werden (das Herausfiltern von Konsonantenschlüsseln ist schneller als das Herausfiltern von Vokalschlüsseln, weil man weniger Einträge nachschlägt). Der Leistungsunterschied kann mit zunehmender Größe des Wörterbuchs sehr wohl geringer werden.

8 Stimmen

Es wäre wahrscheinlich die gleiche Leistung, wenn Sie mydict.iteritems() stattdessen. .items() erstellt eine weitere Liste.

76voto

jnnnnn Punkte 3390

Hier ist ein Beispiel in Python 2.6:

>>> a = {1:1, 2:2, 3:3}
>>> dict((key,value) for key, value in a.iteritems() if key == 1)
{1: 1}

Die Filterung ist der Teil if Erklärung.

Diese Methode ist langsamer als die Antwort von delnan, wenn Sie nur einige wenige von sehr vielen Schlüsseln auswählen wollen.

14 Stimmen

Aber ich würde wahrscheinlich if key in ('x','y','z') Ich denke schon.

1 Stimmen

Wenn Sie bereits wissen, welche Schlüssel Sie benötigen, verwenden Sie die Antwort von Delnan. Wenn Sie jeden Schlüssel mit einer if-Anweisung testen müssen, verwenden Sie die Antwort von ransford.

2 Stimmen

Diese Lösung hat einen weiteren Vorteil. Wenn das Wörterbuch von einem teuren Funktionsaufruf zurückgegeben wird (d.h. a/old_dict ist ein Funktionsaufruf), ruft diese Lösung die Funktion nur einmal auf. In einer imperativen Umgebung ist das Speichern des von der Funktion zurückgegebenen Wörterbuchs in einer Variablen keine große Sache, aber in einer funktionalen Umgebung (z. B. in einem Lambda) ist dies eine wichtige Beobachtung.

32voto

Suor Punkte 2583

Das können Sie tun mit Projekt Funktion aus meiner funky Bibliothek:

from funcy import project
small_dict = project(big_dict, keys)

Werfen Sie auch einen Blick auf wählen_Schlüssel .

29voto

Jim Punkte 526

Dieses Einzeiler-Lambda sollte funktionieren:

dictfilt = lambda x, y: dict([ (i,x[i]) for i in x if i in set(y) ])

Hier ist ein Beispiel:

my_dict = {"a":1,"b":2,"c":3,"d":4}
wanted_keys = ("c","d")

# run it
In [10]: dictfilt(my_dict, wanted_keys)
Out[10]: {'c': 3, 'd': 4}

Es ist ein einfaches Listenverständnis, das über Ihre dict-Schlüssel (i in x) iteriert und eine Liste von Tupelpaaren (Schlüssel, Wert) ausgibt, wenn der Schlüssel in der gewünschten Schlüsselliste (y) enthalten ist. Ein dict() umhüllt das Ganze und gibt es als dict-Objekt aus.

0 Stimmen

Sollte eine set pour wanted_keys aber ansonsten sieht es gut aus.

0 Stimmen

Dadurch erhalte ich ein leeres Wörterbuch, wenn mein ursprüngliches Wörterbuch Listen anstelle von Werten enthält. Gibt es Umgehungsmöglichkeiten?

0 Stimmen

@Francesco, können Sie ein Beispiel nennen? Wenn ich ausführe: dictfilt({'x':['wefwef',52],'y':['iuefiuef','efefij'],'z':['‌​oiejf','iejf']}, ('x','z')) gibt er zurück {'x': ['wefwef', 52], 'z': ['oiejf', 'iejf']} wie beabsichtigt.

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