2009-07-31 5 views
5

Ok, ich bin stecken, brauchen Hilfe von hier ...Filtern von Wörterbüchern und Erstellen von Unterwörterbüchern basierend auf Schlüssel/Werten in Python?

Wenn ich ein Hauptwort-Buch wie dieses haben:

data = [ {"key1": "value1", "key2": "value2", "key1": "value3"}, 
{"key1": "value4", "key2": "value5", "key1": "value6"}, 
{"key1": "value1", "key2": "value8", "key1": "value9"} ] 

Nun, ich brauche schon durch dieses Wörterbuch gehen einige der Daten zu formatieren, das heißt:

for datadict in data: 
    for key, value in datadict.items(): 
    ...filter the data... 

Nun, wie würde ich in der gleichen Schleife irgendwie (wenn möglich ... wenn nicht, Alternativen vorschlagen bitte) für Werte bestimmter Tasten überprüfen, und wenn diese Werte passen Sie meine Voreinstellungen an, dann würde ich diese ganze Liste zu einem anderen Wörterbuch hinzufügen, also effec Ich erstelle kleinere Wörterbücher, wenn ich auf Basis bestimmter Schlüssel und Werte aus dem Hauptwörterbuch herausgehe?

So lassen Sie uns sagen, dass ich ein Unter Wörterbuch mit allen Listen erstellen möchten, in dem Schlüssel1 Wert von „Wert1“ hat, die für die oben aufgeführte Liste mir so etwas wie dieses geben würde:

subdata = [ {"key1": "value1", "key2": "value2", "key1": "value3"}, 
{"key1": "value1", "key2": "value8", "key1": "value9"} ] 
+1

"ein Hauptwörterbuch wie dieses" ist nicht korrekt. Sie haben eine Liste von Wörterbüchern. –

+0

Und Dictionary-Schlüssel sind eindeutig, so dass Sie kein Dictionary mit doppelten Schlüsseln wie dem folgenden erstellen können: {"key1": "value1", "key2": "value2", "key1": "value3"}; Das Ergebnis ist {'key2': 'value2', 'key1': 'value3'}. Wenn Sie die Duplikate wirklich wollen, brauchen Sie eine Liste, also wäre die Gesamtstruktur eine Liste von Listen oder die Wörterbuchwerte sollten Tupel oder Listen sein. –

Antwort

9

Hier ist eine nicht so schöne Art, es zu tun. Das Ergebnis ist ein Generator, aber wenn Sie wirklich eine Liste möchten, können Sie sie mit einem Anruf an list() umschließen. Meist ist es egal.

Das Prädikat ist eine Funktion, die für jedes Schlüssel/Wert-Paar entscheidet, ob ein Wörterbuch in der Liste es schneidet. Der Standardwert akzeptiert alle. Wenn kein k/v-Paar im Wörterbuch übereinstimmt, wird es abgelehnt.

def filter_data(data, predicate=lambda k, v: True): 
    for d in data: 
     for k, v in d.items(): 
       if predicate(k, v): 
        yield d 


test_data = [{"key1":"value1", "key2":"value2"}, {"key1":"blabla"}, {"key1":"value1", "eh":"uh"}] 
list(filter_data(test_data, lambda k, v: k == "key1" and v == "value1")) 
# [{'key2': 'value2', 'key1': 'value1'}, {'key1': 'value1', 'eh': 'uh'}] 
+2

"nicht so hübsch"? Nicht zustimmen. Das ist sehr nett. –

+0

Danke :). Ich denke, dass Treppenhausfunktionen wie diese hässlich sind. – Skurmedel

+1

@Skurmedel: Ihre Funktion ist elegant und es ist leicht zu sehen, wie es die Aufgabe in einfachen Schritten erledigt; Es erspart den Lesern, ein kompliziertes Einzeiler in ihren Köpfen zu parsen. –

1

Die Die Antwort ist zu einfach, daher denke ich, dass uns einige Informationen fehlen. Anyway:

result = [] 
for datadict in data: 
    for key, value in datadict.items(): 
     thefiltering() 

    if datadict.get('matchkey') == 'matchvalue': 
     result.append(datadict) 

Auch Sie "Hauptwörterbuch" ist kein Wörterbuch, sondern eine Liste. Ich wollte das nur klären.

3

Net der Themen zeigte bereits in anderen Kommentaren und Antworten (mehrere identische Schlüssel nicht in einem dict sein kann, etc etc), hier ist, wie ich es tun würde:

def select_sublist(list_of_dicts, **kwargs): 
    return [d for d in list_of_dicts 
      if all(d.get(k)==kwargs[k] for k in kwargs)] 

subdata = select_sublist(data, key1='value1') 
0

Inspiriert durch die Antwort von Skurmedal habe ich dieses in ein rekursives Schema aufgeteilt, um mit einer Datenbank verschachtelter Wörterbücher zu arbeiten. In diesem Fall ist ein "Record" das Subdictionary im Stamm. Das Prädikat definiert, welche Datensätze wir suchen - diejenigen, die mit einem Paar (Schlüssel, Wert) übereinstimmen, in dem diese Paare tief verschachtelt sein können.

def filter_dict(the_dict, predicate=lambda k, v: True): 
    for k, v in the_dict.iteritems(): 
     if isinstance(v, dict) and _filter_dict_sub(predicate, v): 
      yield k, v 

def _filter_dict_sub(predicate, the_dict): 
    for k, v in the_dict.iteritems(): 
     if isinstance(v, dict) and filter_dict_sub(predicate, v): 
      return True 
     if predicate(k, v): 
      return True 
    return False 

Da dies ein Generator ist, müssen Sie möglicherweise mit dict(filter_dict(the_dict)) wickeln ein gefiltertes Wörterbuch zu erhalten.

0

Es ist eine alte Frage, aber aus irgendeinem Grund gibt es keine Einzeiler Syntax Antwort:

{ k: v for k, v in <SOURCE_DICTIONARY>.iteritems() if <CONDITION> } 

Zum Beispiel:

src_dict = { 1: 'a', 2: 'b', 3: 'c', 4: 'd' } 
predicate = lambda k, v: k % 2 == 0 
filtered_dict = { k: v for k, v in src_dict.iteritems() if predicate(k, v) } 

print "Source dictionary:", src_dict 
print "Filtered dictionary:", filtered_dict 

die folgende Ausgabe erzeugen:

Source dictionary: {1: 'a', 2: 'b', 3: 'c', 4: 'd'} 
Filtered dictionary: {2: 'b', 4: 'd'}