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.

9voto

Kevin Grimm Punkte 71

Eine Alternative für den Fall, dass Sie die meisten Schlüssel behalten und einige wenige entfernen möchten:

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

4 Stimmen

Noch kürzer: {k: v for k, v in bigdict.items() if k not in ['l', 'm', 'n']}

7voto

phimuemue Punkte 32518

Vielleicht:

subdict=dict([(x,bigdict[x]) for x in ['l', 'm', 'n']])

Python 3 unterstützt sogar Folgendes:

subdict={a:bigdict[a] for a in ['l','m','n']}

Beachten Sie, dass Sie die Existenz im Wörterbuch wie folgt überprüfen können:

subdict=dict([(x,bigdict[x]) for x in ['l', 'm', 'n'] if x in bigdict])

bzw. für Python 3

subdict={a:bigdict[a] for a in ['l','m','n'] if a in bigdict}

0 Stimmen

Schlägt fehl, wenn a ist nicht in bigdict

0 Stimmen

Die Dinge, von denen es heißt, dass sie nur in Python 3 funktionieren, funktionieren auch in 2.7

7voto

halfdanrump Punkte 363

Sie können auch Folgendes verwenden map (das ist ein très nützliche Funktion, die man auf jeden Fall kennenlernen sollte):

sd = dict(map(lambda k: (k, l.get(k, None)), l))

Beispiel:

large_dictionary = {'a1':123, 'a2':45, 'a3':344}
list_of_keys = ['a1', 'a3']
small_dictionary = dict(map(lambda key: (key, large_dictionary.get(key, None)), list_of_keys))

PS: Ich habe mir die .get(key, None) aus einer früheren Antwort :)

4voto

pandamonium Punkte 109

Okay, das ist etwas, das mich schon ein paar Mal beschäftigt hat, also danke, Jayesh, dass du es gefragt hast.

Die Antworten oben scheinen wie eine gute Lösung als alle, aber wenn Sie diese alle über Ihren Code verwenden, macht es Sinn, die Funktionalität IMHO zu verpacken. Außerdem gibt es hier zwei mögliche Anwendungsfälle: einen, bei dem man sich darum kümmert, ob alle Schlüsselwörter im ursprünglichen Wörterbuch sind, und einen, bei dem das nicht der Fall ist. Es wäre schön, wenn man beide gleich behandeln könnte.

Daher schlage ich vor, eine Unterklasse des Wörterbuchs zu schreiben, z. B.

class my_dict(dict):
    def subdict(self, keywords, fragile=False):
        d = {}
        for k in keywords:
            try:
                d[k] = self[k]
            except KeyError:
                if fragile:
                    raise
        return d

Jetzt können Sie ein Unterwörterbuch herausziehen mit

orig_dict.subdict(keywords)

Beispiele für den Gebrauch:

#
## our keywords are letters of the alphabet
keywords = 'abcdefghijklmnopqrstuvwxyz'
#
## our dictionary maps letters to their index
d = my_dict([(k,i) for i,k in enumerate(keywords)])
print('Original dictionary:\n%r\n\n' % (d,))
#
## constructing a sub-dictionary with good keywords
oddkeywords = keywords[::2]
subd = d.subdict(oddkeywords)
print('Dictionary from odd numbered keys:\n%r\n\n' % (subd,))
#
## constructing a sub-dictionary with mixture of good and bad keywords
somebadkeywords = keywords[1::2] + 'A'
try:
    subd2 = d.subdict(somebadkeywords)
    print("We shouldn't see this message")
except KeyError:
    print("subd2 construction fails:")
    print("\toriginal dictionary doesn't contain some keys\n\n")
#
## Trying again with fragile set to false
try:
    subd3 = d.subdict(somebadkeywords, fragile=False)
    print('Dictionary constructed using some bad keys:\n%r\n\n' % (subd3,))
except KeyError:
    print("We shouldn't see this message")

Wenn Sie den gesamten obigen Code ausführen, sollten Sie (etwa) folgende Ausgabe sehen (entschuldigen Sie die Formatierung):

Original-Wörterbuch:
{'a': 0, 'c': 2, 'b': 1, 'e': 4, 'd': 3, 'g': 6, 'f': 5, 'i': 8, 'h': 7, 'k': 10, 'j': 9, 'm': 12, 'l': 11, 'o': 14, 'n': 13, 'q': 16, 'p': 15, 's': 18, 'r': 17, 'u': 20, 't': 19, 'w': 22, 'v': 21, 'y': 24, 'x': 23, 'z': 25}

Wörterbuch aus ungeraden Tasten:
{'a': 0, 'c': 2, 'e': 4, 'g': 6, 'i': 8, 'k': 10, 'm': 12, 'o': 14, 'q': 16, 's': 18, 'u': 20, 'w': 22, 'y': 24}

subd2 Konstruktion scheitert:
Das ursprüngliche Wörterbuch enthält einige Schlüssel nicht.

Das Wörterbuch wurde unter Verwendung einiger falscher Schlüssel erstellt:
{'b': 1, 'd': 3, 'f': 5, 'h': 7, 'j': 9, 'l': 11, 'n': 13, 'p': 15, 'r': 17, 't': 19, 'v': 21, 'x': 23, 'z': 25}

1 Stimmen

Bei der Unterklassifizierung muss ein bestehendes dict-Objekt in den Typ der Unterklasse konvertiert werden, was teuer sein kann. Warum nicht einfach eine einfache Funktion schreiben subdict(orig_dict, keys, …) ?

0 Stimmen

@musiphil: Ich bezweifle, dass es einen großen Unterschied im Overhead gibt. Das Schöne an der Unterklassenbildung ist, dass die Methode Teil der Klasse ist und nicht importiert oder in-lined werden muss. Das einzige potenzielle Problem oder die einzige Einschränkung des Codes in dieser Antwort ist, dass das Ergebnis pas vom Typ my_dict .

2voto

georg Punkte 634

Noch eine (ich bevorzuge die Antwort von Mark Longair)

di = {'a':1,'b':2,'c':3}
req = ['a','c','w']
dict([i for i in di.iteritems() if i[0] in di and i[0] in req])

0 Stimmen

Seine Langsamkeit für groß Diktat

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