2012-02-16 11 views
7

Quiero eliminarDuplicados de una lista de listas manteniendo la estructura de la sublista intacta.DeleteDuplicates mientras conserva la estructura de la sublista

E.g.

{{1, 7, 8}, {4, 3}, {4, 1, 9}, {9, 2}}

convierte

{{1, 7, 8}, {4, 3}, {9}, {2}}

Ésta es la magnitud de anidación, y sublistas vacías están bien.

+0

Bienvenido a stack exchange. Buena primera pregunta. También puede querer saber sobre el sitio de Mathematica (beta): http://mathematica.stackexchange.com/ – DavidC

Respuesta

11

Este es un truco clásico:

list = {{1, 7, 8}, {4, 3}, {4, 1, 9}, {9, 2}} 

Module[{f}, 
f[x_] := (f[x] = Sequence[]; x); 
Map[f, list, {2}] 
] 

Para entender cómo funciona, considere lo que sucede cuando f[1] se evalúa por primera vez. f[1] se evaluará a (f[1]=Sequence[]); 1, luego a solo 1. Entonces ahora se han hecho definiciones para f[1]. La próxima vez que se evalúe f[1], simplemente se evaluará a Sequence[].

Por lo tanto, la primera vez que se evalúa un argumento para f, devuelve ese argumento. La segunda (o tercera, etc.) vez que se evalúa, devuelve Sequence[]. Sequence[] tiene la propiedad de que se eliminará por completo de las expresiones, es decir, {1, Sequence[], 3} se evaluará a {1, 3}.

En resumen, lo que hace la función es: la primera vez que ve un elemento, reemplaza el elemento consigo mismo (lo deja solo). La segunda vez que ve el mismo elemento, lo elimina. Asigné esta función a "level 2", por lo que solo actuará sobre los elementos de las sublistas.

+0

Szabolcs, ¿podría explicar cómo funciona? – DavidC

+0

@Szabolics Gracias, cuando estaba tratando de atacar esto encontré un código que indicaba que 'Sequence []' podría ser útil. Trataré de descomprimir esto ... ¡cualquier comentario pedagógico sobre la forma en que funciona se agradece! –

+0

+1 para ir [old-school] (http: // stackoverflow.com/a/5248866/618728) –

3

Puede usar Complement para esto y lo único que debe hacer es almacenar todos los elementos que ya ha visto. Al principio, la lista de todos los elementos vistos a está vacía y luego agrega paso a paso todos los números que están en las sublistas. Esta lista acumulada se utiliza en cada paso para borrar todos los números que ya se han visto:

DeleteDuplicatesList[l_List] := 
    Block[{a = {}}, 
    Table[With[{b = a}, 
    a = Union[a, c]; 
    Complement[c, b]], {c, l}] 
    ]; 

l = {{1, 7, 8}, {4, 3}, {4, 1, 9}, {9, 2}}; 
DeleteDuplicatesList[l] 
+0

Gracias, me gusta el enfoque de usar 'Complemento'. Aunque no es obvio por la forma en que planteé el problema inicial, hay un trasfondo teórico de conjunto para todo esto. –

2

No es elegante, pero hace el trabajo:

t = {{1, 7, 8}, {4, 3}, {4, 1, 9}, {9, 2}}; 

Delete[t, Flatten[Rest[Position[t, #]] & /@ (DeleteDuplicates[Flatten[t]]), 1]] 

DeleteDuplicates ... volverá el conjunto , no multi-set, de números en t. Rest[Position[ ... devolverá las posiciones de los duplicados. Delete elimina dichos duplicados.

Cuestiones relacionadas