Evite insertar duplicados en la lista de Python con comprensión

Tengo un diccionario:

XY_dict = {1: [(12, 55),(13, 55)], 2: [(14, 55),(15, 57)], 3: [(14, 55),(15, 58)], 4: [(14, 55),(16, 55)]} 

Quiero saber qué claves tienen valores de tuplas que son únicas (no están presentes en ningún otro valor de clave). En el diccionario de muestra, la clave 1 es única porque ni (12, 55) ni (13, 55) están presentes en ninguna otra clave del diccionario. Al obtener la lista de claves con valores compartidos, puedo invertir el resultado más adelante y obtener las claves que son únicas.

Estoy utilizando una lista de comprensión para obtener claves con valores compartidos:

 keys_shared_values = [k1 for k1,v1 in XY_dict.iteritems() for k,v in XY_dict.iteritems() for XY_pair in v if XY_pair in v1 and k != k1 and k1 not in keys_shared_values] 

Como resultado, estoy obteniendo [2, 2, 3, 3, 4, 4] pero espero que no se inserten duplicados (ya que estoy evaluando si el valor clave está en la lista de resultados). Puedo arreglar eso ejecutando la list(set(shared_values)) , pero me gustaría entender qué está mal con mi código.

El problema es que keys_shared_values está vacío hasta que complete la comprensión, por lo que su k1 not in keys_shared_values siempre devolverá True . No puedes referirte a la comprensión actual. Tu mejor apuesta es convertir para set como ya sugeriste.

Debería cambiar su código a un bucle si desea esa funcionalidad:

 keys_shared_values = [] for k, v in XY_dict.iteritems(): for k1, v1 in XY_dict.iteritems(): for XY_pair in v: if XY_pair in v1 and k != k1 and k1 not in keys_shared_values: keys_shared_values.append(k1) print keys_shared_values 

resultado:

 [3, 4, 2] 

Otros ya han explicado cuál es el problema con la comprensión de su lista. Aquí hay un enfoque alternativo, usar un diccionario de Counter para contar la frecuencia con la que ocurren los diferentes pares xy y usarlo para filtrar las entradas únicas del diccionario.

 >>> from collections import Counter >>> c = Counter(xy for v in XY_dict.values() for xy in v) >>> {k: v for k, v in XY_dict.iteritems() if all(c[xy] == 1 for xy in v)} {1: [(12, 55), (13, 55)]} 

O para obtener las claves con valores compartidos:

 >>> [k for k, v in XY_dict.iteritems() if any(c[xy] > 1 for xy in v)] [2, 3, 4] 

Tenga en cuenta que esto también es más eficiente, ya que compara cada combinación de dos elementos del diccionario, lo que le proporciona una complejidad cuadrática, mientras que este enfoque tiene una complejidad lineal.

Su código no puede funcionar porque key_shared_values no está definido. Si limpia su entorno verá que si intenta ejecutar su ejemplo, obtendrá un NameError: name 'key_shared_values' is not defined error.

Esto se debe a que keys_shared_values no está realmente definido hasta que se ejecuta la statement de comprensión, realmente no puede hacer referencia a ella dentro de la comprensión porque no existe ya.

Si keys_shared_values = [] que predefinirlo, por ejemplo, como keys_shared_values = [] , esto todavía no funcionará, porque cada vez que lo haga referencia en la comprensión, hará referencia al valor de la lista vacía original. Cuando se ejecuta la comprensión, no cambia dinámicamente el valor de keys_shared_values , sino que crea la lista en la memoria y luego la asigna a keys_shared_values .