2016-04-21 5 views
4

Wie ich alle gängigen Unterwörterbuchschlüssel filtere, die in anderen Unterwörterbuchschlüssel in der Mutter WörterbuchFilter gemeinsamen Unter Dictionary-Schlüssel in einem Wörterbuch

d = { 
    '0': {'key_x': 0, 'key_y': 15, 'key_z': 41} 
    '1': {'key_x': 5, 'key_y': 22} 
    '2': {'key_x': 6, 'key_y': 41} 
} 

result ['key_x', 'key_y'] 

aktuelle Lösung ist

intersect = {} 
for k in corner_values.keys(): 
    for j in corner_values[k]: 
     if j not in intersect: 
      intersect[j] = 1 
     else: 
      intersect[j] += 1 

for k in intersect: 
    if intersect[k] != len(corner_values.keys()): 
     del intersect[k] 

vorhanden ist Gibt es dafür eine einfachere Lösung?

Antwort

5

Sie können die Wörterbücher zu setmap und dann reduce mit set.intersection:

>>> from functools import reduce # if you are using Python 3 
>>> d = {      
... '0': {'key_x': 0, 'key_y': 15, 'key_z': 41}, 
... '1': {'key_x': 5, 'key_y': 22}, 
... '2': {'key_x': 6, 'key_y': 41} 
... } 
>>> reduce(set.intersection, map(set, d.values())) 
{'key_x', 'key_y'} 

Hinweis: In Python 3 hat reduce-functools verschoben.

Update: Wie in @ Johns answer, set.intersection kann eine beliebige Anzahl von Sätzen zu behandeln, so dass die reduce ist nicht einmal notwendig. Nur set.intersection(*map(set, d.values()))

3

Sie können eine einzelne set.intersection Operation ausführen, sobald Sie alle Schlüssel extrahieren. Es ist ein Einzeiler dann:

set.intersection(*(set(x) for x in d.itervalues())) 

dass Breaking down, der erste Teil dieser ausgewertet ist:

(set(x) for x in d.itervalues()) 

, dass ein Generator ist, der erzeugt:

{'key_x', 'key_y'}, {'key_x', 'key_y', 'key_z'}, {'key_x', 'key_y'} 

In Python 3, dass Generator entspricht:

map(set, d.values()) 

Aber in Python 2, map ist weniger effizient, weil es eine list konstruiert, die wir nicht benötigen (wie values() statt itervalues()).

In jedem Fall werden die Ergebnisse dieses Generators an set.intersection übergeben (mit dem * Argument Entpacker), um das schwere Heben in einem einzigen Aufruf zu tun.

+0

Nizza. Ich wusste nicht, "Kreuzung" arbeitete "Varargs" -Stil. –

+1

Python 2 hat ['itertools.imap'] (https://docs.python.org/2/library/itertools.html#itertools.imap) –

+0

Auch wenn Sie einen Generator verwenden, wenn Sie eine Funktion damit aufrufen mit '*' werden seine Elemente weiterhin im Container für die Argumente ('* args') gespeichert. Dennoch ist es eine gute Sache, die Zwischenliste zu streichen. –

1

Eine Alternative mit pandas, die Schlüssel müssen nicht bestellt werden:

import pandas as pd 

list(pd.DataFrame(d).dropna().index) 

#['key_x', 'key_y'] 
Verwandte Themen