2012-02-16 9 views
7

Voglio DeleteDuplicates da un elenco di liste mantenendo intatta la struttura di sottolista.DeleteDuplicates pur mantenendo la struttura di sottolista

E.g.

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

diventa

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

Questa è la misura di nesting e sottoliste vuoti sono ok.

+0

Benvenuti nello stack exchange. Bella prima domanda. Potresti anche voler conoscere il sito di Mathematica (beta): http://mathematica.stackexchange.com/ – DavidC

risposta

11

Questo è un trucco classico:

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

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

Per capire come funziona, si consideri cosa succede quando f[1] viene valutata per la prima volta. f[1] valuterà a (f[1]=Sequence[]); 1, quindi a solo 1. Quindi ora sono state fatte delle definizioni per f[1]. La prossima volta che viene valutato f[1], verrà semplicemente valutato su Sequence[].

Quindi, la prima volta che f viene valutata per un argomento, restituisce quell'argomento. Il secondo (o terzo, ecc.) Tempo viene valutato, restituisce Sequence[]. Sequence[] ha la proprietà che verrà completamente rimosso dalle espressioni, ovvero {1, Sequence[], 3} verrà valutato su {1, 3}.

Per riassumere, ciò che fa la funzione è: la prima volta che vede un elemento, sostituisce l'elemento con se stesso (lo lascia da solo). La seconda volta che vede lo stesso elemento, lo rimuove. Ho mappato questa funzione a "level 2", quindi agirà solo sugli elementi delle sottoliste.

+0

Szabolcs, spiegheresti come funziona? – DavidC

+0

@Szabolics Grazie, quando stavo cercando di attaccare questo ho trovato un codice che indicava che 'Sequence []' potrebbe essere utile. Cercherò di decomprimere questo ... qualsiasi commento pedagogico sul modo in cui funziona apprezzato! –

+0

+1 per andare a [old-school] (http: // stackoverflow.it/a/5248866/618728) –

3

Per questo è possibile utilizzare Complement e l'unica cosa che devi fare è archiviare tutti gli elementi che hai già visto. All'inizio l'elenco di tutti gli elementi visti a è vuoto e quindi si aggiungono passo dopo passo tutti i numeri presenti nelle sottoliste. Questo elenco cumulato è utilizzato in ogni passo per cancellare tutti i numeri che sono già stati visti:

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

Grazie, mi piace l'approccio all'uso di 'Complemento'. Sebbene non sia ovvio dal modo in cui ho affermato il problema iniziale, c'è un retroscena teorico dell'insieme di tutto questo. –

2

Non è elegante, ma ottiene il lavoro fatto:

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

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

DeleteDuplicates ... tornerà il set , non multi-set, di numeri in t. Rest[Position[ ... restituirà le posizioni dei duplicati. Delete rimuove detti duplicati.

Problemi correlati