2008-10-03 12 views
6

Esto es realmente sólo es fácil de explicar con un ejemplo, para quitar la intersección de una lista desde el interior de un diccionario que suelo hacer algo como esto:Extracción de un subconjunto de un diccionario de dentro de una lista

a = {1:'', 2:'', 3:'', 4:''} 
exclusion = [3, 4, 5] 

# have to build up a new list or the iteration breaks 
toRemove = [] 
for var in a.iterkeys(): 
    if var in exclusion: 
     toRemove.append(var) 

for var in toRemove: 
    del a[var] 

Esto podría parecer un ejemplo inusual, pero es sorprendente la cantidad de veces que he tenido que hacer algo como esto. Hacer esto con conjuntos sería mucho mejor, pero claramente quiero retener los 'valores' para el dict.

Este método es molesto porque requiere dos bucles y una matriz adicional. ¿Hay una manera más limpia y más eficiente de hacer esto?

Respuesta

12

Considere dict.pop:

for key in exclusion: 
    a.pop(key, None) 

El None mantiene pop de lanzar una excepción cuando key no es una clave.

+0

Oh, esto es mucho mejor que mi respuesta. – SpoonMeiser

+0

buen consejo, dict.pop es olvidado a menudo. – camflan

+0

Puede usar cualquier valor en lugar de None: deleted = [d.pop (k, 0) para k en exclusión] – jfs

2

¿Por qué no usar el método keys, en lugar de iterkeys? De esta forma, puede hacerlo en un bucle porque devuelve una lista, no un iterador.

3
a = dict((key,value) for (key,value) in a.iteritems() if key not in exclusion) 
+0

Esta solución evita bucles explícitos, lo cual es bueno, pero reconstruye el diccionario desde cero, lo que es malo. ¿Tal vez los diccionarios deberían robar algunos métodos de los conjuntos? –

+0

Nunca estoy seguro de la cantidad de beneficios que obtiene al evitar bucles y permanecer en el código C. Supongo que todo dependerá de cuán grande sea tu dict y cuánto de tu eliminación. Creo que la respuesta de Blair sería más eficiente para los dicts grandes, pero tengo que probarlo para estar seguro. –

+0

Es curioso, eliminar la mitad de las claves de un dic 200 (un [i] = i para i dentro del rango (200k)) en un ciclo es aproximadamente un 30% más lento en mi máquina que copiar el dictado. –

1

Puede cambiar su lista de exclusión a un conjunto, luego simplemente use intersección para obtener la superposición.

exclusion = set([3, 4, 5]) 

for key in exclusion.intersection(a): 
    del a[key] 
Cuestiones relacionadas