2012-07-16 24 views
5

Tengo una solución a la siguiente pregunta. Esa solución sería un bucle con una prueba para su inclusión en la salida como la siguiente:¿Por qué la lista de comprensión no filtra los duplicados?

#!/usr/bin/env python 

def rem_dup(dup_list): 
    reduced_list = [] 
    for val in dup_list: 
     if val in reduced_list: 
      continue 
     else: 
      reduced_list.append(val) 

    return reduced_list 

Estoy pidiendo a la siguiente pregunta, porque tengo curiosidad para ver si hay una solución lista por comprensión.

determinado los siguientes datos:

reduced_vals = [] 
vals = [1, 2, 3, 3, 2, 2, 4, 5, 5, 0, 0] 

¿Por qué

reduced_vals = = [x for x in vals if x not in reduced_vals] 

producen la misma lista?

>>> reduced_vals 
[1, 2, 3, 3, 2, 2, 4, 5, 5, 0, 0] 

Creo que tiene algo que ver con el control de la salida (reduced_vals) como parte de una asignación a una lista. Tengo curiosidad, aunque en cuanto a la razón exacta.

Gracias.

+0

Puede acercarse mucho usando [this] (http://stackoverflow.com/a/6197827/355230) answer. – martineau

Respuesta

6

La lista de comprensión crea una nueva lista, mientras que reduced_vals apunta a la lista vacía todo el tiempo durante la evaluación de la lista de comprensión.

La semántica de las asignaciones en Python es: Evalúe el lado derecho y enlace el objeto resultante con el nombre en el lado izquierdo. Una asignación a un nombre simple nunca muta cualquier objeto.

Por cierto, debe usar set() o collections.OrderedDict.fromkeys() para eliminar duplicados de manera eficiente (dependiendo de si necesita conservar el pedido o no).

+0

¿Cómo incluiría colecciones? Solo lo intenté; importó; pero obtuve un error >>> collections.OrderedDict.fromkeys (color) Traceback (última llamada más reciente): Archivo "", línea 1, en NameError: el nombre 'colecciones' no está definido Estoy usando 2.7.x Python – octopusgrabbus

+1

@octopusgrabbus: 'collections' importación colecciones –

+0

>>> >>> importación collections.OrderedDict.fromkeys (de color) Rastreo (llamada más reciente pasado): archivo "", línea 1, en AttributeError: el objeto 'module' no tiene ningún atributo 'OrderedDict' – octopusgrabbus

1

Porque los elementos en la lista de comprensión no están asignados a reduced_vals hasta que se haya construido toda la lista. Use un bucle for con .append() si desea que esto funcione.

+0

Eso ya está sucediendo en el código original (uno sin la 'solución alternativa' del OP) – Dhara

4

Estás comprobando en una lista vacía.

La expresión se evalúa en su totalidad antes de asignarla como el nuevo valor de reduced_vals, que permanece vacío hasta que se haya evaluado la expresión de la lista completa.

En otras palabras, la expresión [x for x in vals if x not in reduced_vals] se ejecuta de forma aislada. Podría ayudar si ve el código de una forma ligeramente modificada:

temp_var = [x for x in vals if x not in reduced_vals] 
reduced_vals = temp_var 
del temp_var 

Lo anterior es el equivalente moral de asignar directamente el resultado de la expresión de lista para reduced_vals, pero se han separado más claramente la asignación del resultado utilizando una segunda variable.

4

En esta línea: [x for x in vals if x not in reduced_vals] no hay un único valor que es no en reduced_vals, como reduced_vals es la lista vacía []. En otras palabras, nada se filtra y se devuelven todos los elementos en vals.

Si intenta esto:

[x for x in vals if x in reduced_vals] 

El resultado es la lista vacía [], como todos los valores no son en reduced_vals (que está vacía). Creo que tiene una confusión con la forma en que la parte de filtrado funciona en una lista de comprensión: ya ve, el filtro solo selecciona los valores que hacen que la condición True, pero no evitará valores duplicados.

Ahora, si lo que necesita es filtrar los duplicados, una comprensión de la lista no es la herramienta adecuada para el trabajo. Para ello, utiliza un conjunto - aunque no necesariamente va a preservar el orden de la lista original, que va a garantizar que los elementos son únicos:

vals = [1, 2, 3, 3, 2, 2, 4, 5, 5, 0, 0] 
list(set(vals)) 
> [0, 1, 2, 3, 4, 5] 
0

Debido reduced_vals no está cambiando durante la evaluación de la lista por comprensión.

Cuestiones relacionadas