Filtraggio di dizionari e creazione di dizionari secondari basati su chiavi / valori in Python?

StackOverflow https://stackoverflow.com/questions/1214968

Domanda

Ok, sono bloccato, ho bisogno di aiuto da qui in poi ...

Se ho un dizionario principale come questo:

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

Ora, devo già consultare quel dizionario per formattare alcuni dei dati, ovvero:

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

Ora, come potrei in qualche modo fare lo stesso loop (se possibile ... in caso contrario, suggerire alternative per favore) controllare i valori di determinate chiavi, e se quei valori corrispondono ai miei preset, aggiungerei l'intero elenco a un altro dizionario , creando in modo efficace dizionari più piccoli mentre esco da questo dizionario principale basato su determinate chiavi e valori?

Quindi, diciamo che voglio creare un sotto-dizionario con tutti gli elenchi in cui key1 ha valore di " value1 " ;, che per l'elenco sopra mi darebbe qualcosa del genere:

subdata = [ {"key1": "value1", "key2": "value2", "key1": "value3"},  
{"key1": "value1", "key2": "value8", "key1": "value9"} ]
È stato utile?

Soluzione

Ecco un modo non abbastanza carino di farlo. Il risultato è un generatore, ma se vuoi davvero un elenco puoi circondarlo con una chiamata a list () . Principalmente non importa.

Il predicato è una funzione che decide per ogni coppia chiave / valore se un dizionario nell'elenco lo taglierà. Quello predefinito accetta tutto. Se nessuna coppia k / v nel dizionario corrisponde, viene rifiutata.

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'}]

Altri suggerimenti

Al netto dei problemi già evidenziati in altri commenti e risposte (più chiavi identiche non possono essere in un dict, ecc. ecc.), ecco come lo farei:

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')

La risposta è troppo semplice, quindi immagino che manchino alcune informazioni. Ad ogni modo:

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

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

Inoltre, tu " dizionario principale " non è un dizionario ma un elenco. Volevo solo chiarirlo.

Ispirato dalla risposta di Skurmedal, l'ho diviso in uno schema ricorsivo per lavorare con un database di dizionari nidificati. In questo caso, un "record" è il sottotitolo nel trunk. Il predicato definisce quali record stiamo cercando - quelli che corrispondono ad alcune coppie (chiave, valore) in cui queste coppie possono essere nidificate in profondità.

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

Poiché si tratta di un generatore, potrebbe essere necessario avvolgere con dict (filter_dict (the_dict)) per ottenere un dizionario filtrato.

È una vecchia domanda, ma per qualche motivo non esiste una risposta di sintassi a una riga:

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

Ad esempio:

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

Produrrà il seguente output:

Source dictionary: {1: 'a', 2: 'b', 3: 'c', 4: 'd'}
Filtered dictionary: {2: 'b', 4: 'd'}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top