Il modo più veloce per eliminare i duplicati in un elenco di parole di grandi dimensioni?


14

Devo deduplicare un ampio elenco di parole. Ho provato diversi comandi e ho fatto alcune ricerche qui e qui in cui spiegano che il modo più veloce per deduplicare un elenco di parole sembra usare awk.

awk -> O (n)? ordina -> O (n registro n)?

Tuttavia ho scoperto che questo sembra non essere vero. Ecco i miei risultati dei test:

sort -u input.txt -o output.txt 

reale 0m12.446s
utente 0m11.347s
sys 0m0.906s

awk '!x[$0]++' input.txt > output.txt

reale 0m47.221s
utente 0m45.419s
sys 0m1.260s

Quindi usare sort -u è 3,7 volte più veloce. Perchè è questo? esiste un metodo ancora più veloce per eseguire la deduplicazione?

*********** Aggiornare ********

Come qualcuno ha sottolineato nei commenti, potrebbe essere che la mia lista di parole fosse già stata ordinata in una certa misura. Per escludere questa possibilità ho generato due liste di parole usando questo script Python .

Elenco1 = 7 Mb
Elenco2 = 690 Mb

Risultati AWK:
List1
real 0m1.643s
user 0m1.565s
sys 0m0.062s

List2
reali 2m6.918s
utente 2m4.499s
sys 0m1.345s

ORDINA risultati:
List1
real 0m0.724s
user 0m0.666s
sys 0m0.048s

List2
reali 1m27.254s
utente 1m25.013s
sys 0m1.251s


È possibile che i tuoi dati di input siano già ordinati?
Iruvar,


2
La notazione O grande riguarda ciò che accade quando la lunghezza dell'input si avvicina all'infinito: ti dice che un algoritmo si ridimensiona con un input grande. Alcuni algoritmi funzionano meglio su input di piccole dimensioni.
ctrl-alt-delor,

1
Karlpy, in quale ordine hai eseguito, prima o per caso? Ciò potrebbe fare la differenza a causa della memorizzazione dei file nella cache
iruvar,

1
@karlpy: "Ho cambiato il nome del file ..." Se vuoi dire che hai rinominato il file, non è abbastanza buono. Rinominare un file associa semplicemente un nuovo nome al vecchio inode, che punta ancora agli stessi vecchi blocchi di dati. Se sono stati memorizzati nella cache, sono ancora memorizzati nella cache. ISTM che una tecnica molto migliore sarebbe quella di (1) fare una copia del file, quindi (2) eseguire un comando su un file e (3) eseguire l'altro comando sull'altro file.
Scott,

Risposte:


3

Stai ponendo la domanda sbagliata, o ponendo la domanda in modo errato e nello stack sbagliato, questa è una domanda migliore da porre nella programmazione / stack-overflow affinché le persone possano darti risposte basate sugli algoritmi utilizzati all'interno di awk e sort.

PS: fai anche il necessario con nawk, mawk e gawk per darci qualche dettaglio in più in "zona in";) e esegui le corse come 100 volte ciascuna con la deviazione minima, massima, media e standard.

Comunque sia, torniamo alla domanda attuale, da CompSci 210, riguarda gli algoritmi utilizzati. L'ordinamento fa uso di diversi, a seconda delle dimensioni e dei vincoli di memoria che colpisce per salvare i file sul disco in file temporanei da unire in ordine una volta esaurita la memoria, e dovrai guardare nel codice sorgente per vedere cosa lo specifico comando sort (1) utilizza sul sistema operativo specifico su cui lo stai eseguendo, ma per esperienza sta caricando nella memoria il più possibile, esegui un rapido ordinamento su di esso, scrivi sul disco, risciacqua ripetizione e al alla fine eseguirà una fusione-ordinamento dei piccoli file ordinati. Quindi qui avrai O (n * log2 (N)) per le parti, quindi un'operazione di fusione O (n * log (n)) approssimativa

awk: il meccanismo x [$ 0] ++ è "supponiamo" di utilizzare l'hash. MA il problema con l'hash, una presunta operazione di "ricerca" O (1), è la collisione e la gestione delle collisioni. Ciò potrebbe causare un problema quando i dati non sono ben distribuiti, né riempire i secchi ecc. E in elenchi di grandi dimensioni, l'hash potrebbe essere un grosso problema di memoria se la gestione delle collisioni non viene eseguita correttamente (e potrebbe essere necessario ottimizzare gli algoritmi di hashing per i dati previsti), quindi è necessario esaminare le prestazioni delle funzioni di hashing effettive e quindi O (1) potrebbe essere più vicino a una O (log (n)) per gli inserti (Ie. O (1) per la prima ricerca, e se NON esiste aggiungilo che potrebbe essere O (log (n))), e che quindi n * O (1) diventa un * O (log (n)) = > O (n * log (n)), per non parlare del fatto che stai anche facendo le cose in modo "interpretato" :)


-2

La differenza di velocità è perché 'sort' è un comando ( link ), mentre 'awk' è un linguaggio di programmazione ( link ).

Il comando 'sort' prende input e restituisce output. Considerando che 'awk' è un linguaggio di programmazione, che prima interpreta il codice (comando terminale), quindi inizia l'elaborazione su di esso. Semplice come quella.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.