[RISOLTO] [awk?] eliminare duplicati da lista disordinata
Moderatore: Staff
Regole del forum
1) Citare sempre la versione di Slackware usata, la versione del Kernel e magari anche la versione della libreria coinvolta. Questi dati aiutano le persone che possono rispondere.
2) Per evitare confusione prego inserire in questo forum solo topic che riguardano appunto Gnu/Linux in genere, se l'argomento è specifico alla Slackware usate uno dei forum Slackware o Slackware64.
3) Leggere attentamente le risposte ricevute
4) Scrivere i messaggi con il colore di default, evitare altri colori.
5) Scrivere in Italiano o in Inglese, se possibile grammaticalmente corretto, evitate stili di scrittura poco chiari, quindi nessuna abbreviazione tipo telegramma o scrittura stile SMS o CHAT.
6) Appena registrati è consigliato presentarsi nel forum dedicato.
La non osservanza delle regole porta a provvedimenti di vari tipo da parte dello staff, in particolare la non osservanza della regola 5 porta alla cancellazione del post e alla segnalazione dell'utente. In caso di recidività l'utente rischia il ban temporaneo.
1) Citare sempre la versione di Slackware usata, la versione del Kernel e magari anche la versione della libreria coinvolta. Questi dati aiutano le persone che possono rispondere.
2) Per evitare confusione prego inserire in questo forum solo topic che riguardano appunto Gnu/Linux in genere, se l'argomento è specifico alla Slackware usate uno dei forum Slackware o Slackware64.
3) Leggere attentamente le risposte ricevute
4) Scrivere i messaggi con il colore di default, evitare altri colori.
5) Scrivere in Italiano o in Inglese, se possibile grammaticalmente corretto, evitate stili di scrittura poco chiari, quindi nessuna abbreviazione tipo telegramma o scrittura stile SMS o CHAT.
6) Appena registrati è consigliato presentarsi nel forum dedicato.
La non osservanza delle regole porta a provvedimenti di vari tipo da parte dello staff, in particolare la non osservanza della regola 5 porta alla cancellazione del post e alla segnalazione dell'utente. In caso di recidività l'utente rischia il ban temporaneo.
- ZeroUno
- Staff

- Messaggi: 5441
- Iscritto il: ven 2 giu 2006, 14:52
- Nome Cognome: Matteo Rossini
- Slackware: current
- Kernel: slack-current
- Desktop: ktown-latest
- Distribuzione: 01000000-current
- Località: Roma / Castelli
- Contatta:
[RISOLTO] [awk?] eliminare duplicati da lista disordinata
E' un problema che ebbi diverso tempo fa.
Non mi ricordo se chiesi quì o su usenet, ma non mi ricordo bene il comando per risolvere.
Supponiamo di avere una lista
ciao
pippo
pluto
topolino
pluto
minni
paperone
ciao
paperino
questa lista contiene dei duplicati che io voglio rimuovere.
il classico è sort -u, ma questo ha il difetto di lasciarmi la lista ordinata alfabeticamente, mentre io voglio ottenere
ciao
pippo
pluto
topolino
minni
paperone
paperino
cioè eliminate solo le seconde entry duplicate.
qualcuno per risolvere mi aveva detto awk con una certa sintassi, ma non me la ricordo più e non sono molto esperto (di awk conosco {print $1} e poco più).
Chi la sa?
Non mi ricordo se chiesi quì o su usenet, ma non mi ricordo bene il comando per risolvere.
Supponiamo di avere una lista
ciao
pippo
pluto
topolino
pluto
minni
paperone
ciao
paperino
questa lista contiene dei duplicati che io voglio rimuovere.
il classico è sort -u, ma questo ha il difetto di lasciarmi la lista ordinata alfabeticamente, mentre io voglio ottenere
ciao
pippo
pluto
topolino
minni
paperone
paperino
cioè eliminate solo le seconde entry duplicate.
qualcuno per risolvere mi aveva detto awk con una certa sintassi, ma non me la ricordo più e non sono molto esperto (di awk conosco {print $1} e poco più).
Chi la sa?
Ultima modifica di ZeroUno il dom 12 set 2010, 0:36, modificato 1 volta in totale.
Packages finder: slakfinder.org | Slackpkg+, per aggiungere repository a slackpkg
Codice: Seleziona tutto
1011010 1100101 1110010 1101111 - 0100000 - 1010101 1101110 1101111Re: [awk?] eliminare duplicati da lista disordinata
La soluzione più semplice sarebbe usare una hash table.
- Trotto@81
- Iper Master

- Messaggi: 3559
- Iscritto il: sab 26 giu 2004, 0:00
- Nome Cognome: Andrea
- Slackware: Slackware64 14.2 bet
- Kernel: default
- Desktop: KDE 4.14.14
- Località: Monasterace M. (RC)
- Contatta:
Re: [awk?] eliminare duplicati da lista disordinata
Mario Vanoni saprò di certo aiutarti, senza nulla togliere agli altri. 
- ZeroUno
- Staff

- Messaggi: 5441
- Iscritto il: ven 2 giu 2006, 14:52
- Nome Cognome: Matteo Rossini
- Slackware: current
- Kernel: slack-current
- Desktop: ktown-latest
- Distribuzione: 01000000-current
- Località: Roma / Castelli
- Contatta:
Re: [awk?] eliminare duplicati da lista disordinata
?!?!?appo ha scritto:La soluzione più semplice sarebbe usare una hash table.
che intendi per usare una hash table?
se devo usare una cosa complicata uso questa:
Codice: Seleziona tutto
$ cat -n lista|sort -k2 |uniq -f1|sort -n|cut -f2-EDIT: ho ritrovato il post, ed è decisamente una soluzione più elegante
Codice: Seleziona tutto
$ awk '!a[$0]++' listanon sarei mai riuscito a ricostruirla da solo:
antani ha scritto:Quello che fa il programma e' molto semplice, lo puoi riscrivere cosi' che
probabilmente e' piu' leggibile:se a[<chiave>] vale 0, allora stampa la riga. Poi a[<chiave>] vieneCodice: Seleziona tutto
awk '!a[$0]{print} {a[$0]++}' file
incrementato di 1, Questo significa che verranno stampate solo le righe con
la prima occorrenza della chiave nel file.
Packages finder: slakfinder.org | Slackpkg+, per aggiungere repository a slackpkg
Codice: Seleziona tutto
1011010 1100101 1110010 1101111 - 0100000 - 1010101 1101110 1101111- joseph
- Linux 2.x

- Messaggi: 206
- Iscritto il: lun 14 giu 2010, 23:50
- Slackware: 15.0
- Kernel: 5.15.27
- Desktop: xfce
- Località: Salerno
Re: [RISOLTO] [awk?] eliminare duplicati da lista disordinat
Carina questa. Sinceramente non sapevo di tutte queste potenzialità di awk, mi sa che dovrò studiarmelo a fondo 
Re: [awk?] eliminare duplicati da lista disordinata
Sull'efficienza non sono d'accordo. Ad ogni modo io mi occupo di teoriaZeroUno ha scritto:?!?!?appo ha scritto:La soluzione più semplice sarebbe usare una hash table.
che intendi per usare una hash table?
se devo usare una cosa complicata uso questa:ma quella in awk era più carina e performante.Codice: Seleziona tutto
$ cat -n lista|sort -k2 |uniq -f1|sort -n|cut -f2-
- ZeroUno
- Staff

- Messaggi: 5441
- Iscritto il: ven 2 giu 2006, 14:52
- Nome Cognome: Matteo Rossini
- Slackware: current
- Kernel: slack-current
- Desktop: ktown-latest
- Distribuzione: 01000000-current
- Località: Roma / Castelli
- Contatta:
Re: [awk?] eliminare duplicati da lista disordinata
Io mi occupo di pratica... se una cosa è sballata nella teoria e nella forma ma funziona beh... la uso!!appo ha scritto:Ad ogni modo io mi occupo di teoria.
Packages finder: slakfinder.org | Slackpkg+, per aggiungere repository a slackpkg
Codice: Seleziona tutto
1011010 1100101 1110010 1101111 - 0100000 - 1010101 1101110 1101111Re: [awk?] eliminare duplicati da lista disordinata
Recito la parte dello spocchioso. Quanto è lunga la lista? Quanti elementi distinti, in termini di valore atteso, ci saranno?ZeroUno ha scritto:Io mi occupo di pratica... se una cosa è sballata nella teoria e nella forma ma funziona beh... la uso!!appo ha scritto:Ad ogni modo io mi occupo di teoria.
Senza entrare nella speciosa diàtriba tra teoria e pratica: quello che funziona una volta non è garantito che funzioni sempre
- ZeroUno
- Staff

- Messaggi: 5441
- Iscritto il: ven 2 giu 2006, 14:52
- Nome Cognome: Matteo Rossini
- Slackware: current
- Kernel: slack-current
- Desktop: ktown-latest
- Distribuzione: 01000000-current
- Località: Roma / Castelli
- Contatta:
Re: [awk?] eliminare duplicati da lista disordinata
E' chiaro che l'algoritmo ha complessità O(N^2), e credo che anche nella teoria non si possa fare molto meglio, al limite O(N*log N)... (ebbene si, anche io ho studiato la teoria
); ho i miei dubbi che si possa raggiungere O(N).
E' chiaro anche, come dici, che dipende dai casi.
Nel caso attuale la lista non supera i 100 elementi e non è possibile cacharli perchè la lista su cui operare è diversa ad ogni esecuzione
Per numeri così piccoli, O(N^2) e O(N) non differiscono di molto.
Quello che provai a suo tempo aveva una lista di 500000 elementi e questo awk mi dava una performance decente, sicuramente migliore (ma moooolto migliore) di quello che feci io a suo tempo:
entrambi gli algoritmi hanno O(N^2)
anche il metodo sopradescritto
ha complessità O(N^2)
Ma quello che conta in un programma non è solamente O(qualcosa).
Quì compare:
1) il K, cioè il fattore moltiplicativo di O, che non so perchè mi è stato insegnato che se con un algoritmo ci voglio due istruzioni per elaborare un dato, e se con un algoritmo ce ne vuole uno, quando elabori N dati comunque si scrive O(N). Nel caso attuale, K influisce molto perchè è il tempo di accesso al disco. Nel caso dell'algoritmo con il ciclo for, ad ogni ciclo deve venir caricato il comando grep e pippo.txt (per fortuna esiste la cache). l'altro comando carica subito 5 comandi fissi in ram, ma deve eseguire 3 manipolazioni testuali e 2 ordinamenti. l'awk fa due accessi al disco, uno per il caricamento di awk e uno per il caricamento della lista (che poi, nel mio caso, viene fornita in pipe)
2) la ram che occupa. In questo caso ha poco senso perchè i numeri sono piccoli. Ma ho fatto recentemente un programma che per aumentare le performance teneva in ram dati ridondanti. I numeri sono cresciuti e la ram dedicata al programma (16M) è schioppata. Ho dovuto rifare buona parte dell'algoritmo.
3) la semplicità di scrittura e il tempo per scriverlo. talvolta preferisco fare un algoritmo non ottimizzato, ma semplice e veloce da scrivere (e da leggere) piuttosto che mettermi a fare 100 calcoli per scoprire quello migliore. E' quindi prassi comune fare due comandi quando è possibile darne uno.
4) l'eleganza (e si, va contato pure questo), sia di come è scritto sia di come esegue. scrivere awk ecc al posto di un grosso algoritmo più ottimizzato è decisamente meglio.
5) il collo di bottiglia. se so elaborare velocemente i dati, ma la fonte li genera lentamente è tutto un cavolo che mi sono scervellato.
6) appunto la diatriba tra teoria e pratica che dici... quello che funziona una volta non è garantito che funziona sempre, ma se l'insieme dei dati rientra in quelle che hanno già funzionato, non mi interessa che per altri casi potrebbe non funzionare. Per esempio, il caso con il for è sicuro che non funziona se all'interno del file ci sono spazi. Anzi, fastidio gli danno pure i punti (che grep interpreta come carattre jolly). E ancora, sempre nel caso del for, l'algoritmo non funziona se nel file ci sono parole e sottoinsiemi di queste parole
7) la probabilità di bug. più un algoritmo è complesso più ci può scappare il bug, anche se la teoria non contempla questo fattore
murphy: "dato un algoritmo deve accettare dati inseriti dall'utente, se l'algoritmo è stato scritto per contemplare tutte le possibili problematiche, l'utente puntualmente scoverà una unica eccezione che è sfuggita al programmatore"
vabbé, ho esagerato un poco, si potrebbe litigare all'infinito,
ingegneri informatici contro informatici teorici, fisici contro matematici, sistemisti contro programmatori.
Io sono un sistemista, e i sistemisti gli servono le cose veloci da ottenere, anche se approssimative.
Come programmatore mi ci diletto e basta.
E' chiaro anche, come dici, che dipende dai casi.
Nel caso attuale la lista non supera i 100 elementi e non è possibile cacharli perchè la lista su cui operare è diversa ad ogni esecuzione
Per numeri così piccoli, O(N^2) e O(N) non differiscono di molto.
Quello che provai a suo tempo aveva una lista di 500000 elementi e questo awk mi dava una performance decente, sicuramente migliore (ma moooolto migliore) di quello che feci io a suo tempo:
Codice: Seleziona tutto
cat pippo.txt |cut -c-1|sort -u >lista.txt
for a in `cat lista.txt`;do grep -m 1 ^$a pippo.txt;done anche il metodo sopradescritto
Codice: Seleziona tutto
$ cat -n lista|sort -k2 |uniq -f1|sort -n|cut -f2-Ma quello che conta in un programma non è solamente O(qualcosa).
Quì compare:
1) il K, cioè il fattore moltiplicativo di O, che non so perchè mi è stato insegnato che se con un algoritmo ci voglio due istruzioni per elaborare un dato, e se con un algoritmo ce ne vuole uno, quando elabori N dati comunque si scrive O(N). Nel caso attuale, K influisce molto perchè è il tempo di accesso al disco. Nel caso dell'algoritmo con il ciclo for, ad ogni ciclo deve venir caricato il comando grep e pippo.txt (per fortuna esiste la cache). l'altro comando carica subito 5 comandi fissi in ram, ma deve eseguire 3 manipolazioni testuali e 2 ordinamenti. l'awk fa due accessi al disco, uno per il caricamento di awk e uno per il caricamento della lista (che poi, nel mio caso, viene fornita in pipe)
2) la ram che occupa. In questo caso ha poco senso perchè i numeri sono piccoli. Ma ho fatto recentemente un programma che per aumentare le performance teneva in ram dati ridondanti. I numeri sono cresciuti e la ram dedicata al programma (16M) è schioppata. Ho dovuto rifare buona parte dell'algoritmo.
3) la semplicità di scrittura e il tempo per scriverlo. talvolta preferisco fare un algoritmo non ottimizzato, ma semplice e veloce da scrivere (e da leggere) piuttosto che mettermi a fare 100 calcoli per scoprire quello migliore. E' quindi prassi comune fare due comandi quando è possibile darne uno.
4) l'eleganza (e si, va contato pure questo), sia di come è scritto sia di come esegue. scrivere awk ecc al posto di un grosso algoritmo più ottimizzato è decisamente meglio.
5) il collo di bottiglia. se so elaborare velocemente i dati, ma la fonte li genera lentamente è tutto un cavolo che mi sono scervellato.
6) appunto la diatriba tra teoria e pratica che dici... quello che funziona una volta non è garantito che funziona sempre, ma se l'insieme dei dati rientra in quelle che hanno già funzionato, non mi interessa che per altri casi potrebbe non funzionare. Per esempio, il caso con il for è sicuro che non funziona se all'interno del file ci sono spazi. Anzi, fastidio gli danno pure i punti (che grep interpreta come carattre jolly). E ancora, sempre nel caso del for, l'algoritmo non funziona se nel file ci sono parole e sottoinsiemi di queste parole
7) la probabilità di bug. più un algoritmo è complesso più ci può scappare il bug, anche se la teoria non contempla questo fattore
vabbé, ho esagerato un poco, si potrebbe litigare all'infinito,
ingegneri informatici contro informatici teorici, fisici contro matematici, sistemisti contro programmatori.
Io sono un sistemista, e i sistemisti gli servono le cose veloci da ottenere, anche se approssimative.
Come programmatore mi ci diletto e basta.
Packages finder: slakfinder.org | Slackpkg+, per aggiungere repository a slackpkg
Codice: Seleziona tutto
1011010 1100101 1110010 1101111 - 0100000 - 1010101 1101110 1101111Re: [RISOLTO] [awk?] eliminare duplicati da lista disordinat
Oh, mamma, non volevo scatenare sto casino! 
Solo qualche precisazione: quando lavori in memoria esterna, non usi la notazione O() in termini di numero di operazioni ma in termini di accessi alla memoria esterna. È il cosiddetto modello I/O.
In particolar modo, in tale modello, si trascurano tutte le operazioni effettuare in RAM, cosa per altro assai discutibile al giorno d'oggi. Ed il K di cui parli, quando si tratta di RAM, non si riferisce agli accessi alla memoria ma al fattore due a cui fai riferimento.
A parte queste piccolezze, capisco benissimo il tuo discorso e di fatto, come ho detto nel mio post, la mia era una amichevole provocazione, per usare un termine eccessivo.
Poi, "che te devo di'", c'è chi preferisce quick sort a merge sort!
Solo qualche precisazione: quando lavori in memoria esterna, non usi la notazione O() in termini di numero di operazioni ma in termini di accessi alla memoria esterna. È il cosiddetto modello I/O.
In particolar modo, in tale modello, si trascurano tutte le operazioni effettuare in RAM, cosa per altro assai discutibile al giorno d'oggi. Ed il K di cui parli, quando si tratta di RAM, non si riferisce agli accessi alla memoria ma al fattore due a cui fai riferimento.
A parte queste piccolezze, capisco benissimo il tuo discorso e di fatto, come ho detto nel mio post, la mia era una amichevole provocazione, per usare un termine eccessivo.
Poi, "che te devo di'", c'è chi preferisce quick sort a merge sort!
- ZeroUno
- Staff

- Messaggi: 5441
- Iscritto il: ven 2 giu 2006, 14:52
- Nome Cognome: Matteo Rossini
- Slackware: current
- Kernel: slack-current
- Desktop: ktown-latest
- Distribuzione: 01000000-current
- Località: Roma / Castelli
- Contatta:
Re: [RISOLTO] [awk?] eliminare duplicati da lista disordinat
Non ricordo bene la differenza tra i due (che poi ce ne sono altri no? tipo il bubble sort e qualcun altro) in termini concettuale di forma, algoritmo e performance, ma se il primo si traduce letteralmente "ordinamento _semplice_" lo preferiscoappo ha scritto:Poi, "che te devo di'", c'è chi preferisce quick sort a merge sort!
Tempo fa sono andato a vedere il sorgente di sort. Mi sembra che divide il file in chunk su file temporanei e li ordina, e poi alla fine li mette insieme.... questo è un merge sort?
Se ho capito bene si: Merge sort, Quicksort
A dire la verità c'è una cosa che preferisco di più di scrivere un algoritmo semplice...... non scriverlo affatto
Beh, si, da come parlo sto mandando a farsi friggere i tre anni di studio alle superiori e i due esami di informatica all'università... ma che importa... basta che funziona......
In fondo di tutti i (pochi) esami che ho fatto, l'unico che veramente ho usato è 'sistemi operativi'.
Comunque, tornando al topic originale, tu come avresti fatto questo programma?
Packages finder: slakfinder.org | Slackpkg+, per aggiungere repository a slackpkg
Codice: Seleziona tutto
1011010 1100101 1110010 1101111 - 0100000 - 1010101 1101110 1101111