2009-07-31 18 views
5

Ok, estoy atascado, necesitan algo de ayuda de aquí en adelante ...¿Filtrado de diccionarios y creación de diccionarios secundarios basados ​​en claves/valores en Python?

Si Tengo un diccionario principal de esta manera:

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

Ahora, tengo que ir a través de ese diccionario ya formatear algunos de los datos, es decir:

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

Ahora, ¿cómo voy en el mismo bucle de alguna manera (si es posible ... si no, por favor, sugerir alternativas) para comprobar los valores de ciertas teclas, y si esos valores coincidir con mis preajustes luego agregaría esa lista completa a otro diccionario, por lo tanto efecto ¿Cómo puedo crear diccionarios más pequeños a medida que avanzo en este diccionario principal en función de ciertas claves y valores?

Por lo tanto, digamos que quiero crear un sub-diccionario con todas las listas en las que key1 tiene un valor de "valor1", que para la lista anterior me daría algo como esto:

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

"un diccionario principal como este" no es correcto. Usted tiene una lista de diccionarios. –

+0

Y las claves del diccionario son únicas, por lo que no puede construir un diccionario con claves duplicadas como las siguientes: {"clave1": "valor1", "clave2": "valor2", "clave1": "valor3"}; el resultado es {'clave2': 'valor2', 'clave1': 'valor3'}. Si realmente desea los duplicados, necesitará una lista, por lo que la estructura general sería una lista de listas o los valores del diccionario deberían ser tuplas o listas. –

Respuesta

9

Aquí hay una manera no tan bonita de hacerlo. El resultado es un generador, pero si realmente quieres una lista, puedes rodearla con una llamada al list(). En general, no importa.

El predicado es una función que decide para cada par clave/valor si un diccionario en la lista va a cortarlo. El predeterminado acepta todo. Si no hay k/v-pair en el diccionario coincide, se rechaza.

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

"no tan bonito"? Discrepar. Esto esta muy bien. –

+0

Gracias :). Tiendo a pensar que las funciones de escalera son feas. – Skurmedel

+1

@Skurmedel: Su función es elegante y es fácil ver cómo hace el trabajo en simples pasos; ahorra a los lectores tener que analizar un complicado delineador en sus cabezas. –

1

El la respuesta es muy simple, así que creo que nos falta algo de información. De todos modos:

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

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

Además, tu "diccionario principal" no es un diccionario sino una lista. Sólo quería aclararlo.

3

neto de las cuestiones ya se ha señalado en otros comentarios y respuestas (múltiples llaves idénticas no pueden estar en un diccionario, etc, etc), así es como yo lo haría:

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

Inspirado por la respuesta de Skurmedal, dividí esto en un esquema recursivo para trabajar con una base de datos de diccionarios anidados. En este caso, un "registro" es el subordinado en el tronco. El predicado define qué registros buscamos: aquellos que coinciden con algún par (clave, valor) donde estos pares pueden estar profundamente anidados.

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 

Como se trata de un generador, es posible que necesite para envolver con dict(filter_dict(the_dict)) para obtener un diccionario filtrada.

0

Es una vieja pregunta, pero por alguna razón no hay una sola línea respuesta sintaxis:

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

Por ejemplo:

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 

producirá el siguiente resultado:

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