Tengo un archivo de texto con 2 millones de líneas. Cada línea tiene un entero positivo. Estoy tratando de formar un tipo de tabla de frecuencias.
Fichero de entrada:
3
4
5
8
La salida debe ser:
3
7
12
20
¿Cómo voy a hacer esto?
                    
                        command-line
                                text-processing
                                
                    
                    
                        Monty Harder
fuente
                
                fuente

Respuestas:
Con
awk:$0Es la línea actual. Entonces, para cada línea, lo agrego atotal, establezco la línea en la nuevatotal, y luego el final1es un atajo awk: imprime la línea actual para cada condición verdadera, y1como condición se evalúa como verdadera.fuente
printpuede usar la palabra también?print total}lugar de$0 = total}1{print(total += $0)}En un script de python:
Usar
add_last.pyEjecútelo con el archivo de origen y el archivo de salida de destino como argumentos:
Explicación
El código es bastante legible, pero en detalle:
Abrir archivo de salida para escribir resultados
Abrir archivo de entrada para leer por línea
Lea las líneas y agregue el valor de la nueva línea al total:
Escriba el resultado en el archivo de salida:
fuente
Solo por diversión
Esto funciona mediante una pendiente
+pa cada línea de la entrada, y luego pasando el resultado a ladccalculadora dondeentonces
El
-e0argumento empuja0a ladcpila para inicializar la suma.fuente
real 0m4.234sEn Bash:
fuente
real 0m53.116scasi un minuto, en 1.3 millones de líneas :)Para imprimir sumas parciales de enteros dados en la entrada estándar, uno por línea:
Ejemplo ejecutable .
Si por alguna razón el comando es demasiado lento; podrías usar el programa C:
Para construirlo y ejecutarlo, escriba:
Ejemplo ejecutable .
UINTMAX_MAXes18446744073709551615.El código C es varias veces más rápido que el comando awk en mi máquina para el archivo de entrada generado por:
fuente
accumulate()itertoolProbablemente quieras algo como esto:
Explicación del comando:
sort -n <filename> | uniq -cordena la entrada y devuelve una tabla de frecuencias| awk 'BEGIN{print "Number\tFrequency"}{print $2"\t"$1}'convierte la salida en un formato más agradableEjemplo:
archivo de entrada
list.txt:El comando:
fuente
Puedes hacer esto en vim. Abra el archivo y escriba las siguientes teclas:
Tenga en cuenta que en
<C-a>realidad es ctrl-a, y<cr>es retorno de carro , es decir, el botón enter.Así es como funciona esto. En primer lugar, queremos borrar el registro 'a' para que no tenga efectos secundarios la primera vez. Esto es simplemente
qaq. Luego hacemos lo siguiente:Después de que esta macro recursiva haya terminado de ejecutarse, simplemente llamamos
:wq<cr>para guardar y salir.fuente
Perl one-liner:
Con 2.5 millones de líneas de números, el procesamiento tarda aproximadamente 6.6 segundos:
fuente
real 0m0.908s, muy agradable.Un simple Bash de una sola línea:
xes la suma acumulada de todos los números de la línea actual y superior.nes el número en la línea actual.Nos bucle sobre todas las líneas
ndeINPUT_FILEy añadir su valor numérico para la variablexe imprimir esa suma durante cada iteración.Sin embargo, Bash es un poco lento aquí, puede esperar que esto se ejecute alrededor de 20-30 segundos para un archivo con 2 millones de entradas, sin imprimir el resultado en la consola (que es aún más lento, independientemente del método que utilice).
fuente
Similar a la respuesta de @ steeldriver, pero con un poco menos arcano en su
bclugar:Lo bueno de
bc(ydc) es que son calculadoras de precisión arbitrarias, por lo que nunca se desbordarán ni sufrirán falta de precisión sobre los enteros.La
sedexpresión transforma la entrada en:Esto luego es evaluado por
bc. Laavariable bc se inicializa automáticamente a 0. Cada línea se incrementaa, luego la imprime explícitamente.fuente
real 0m5.642sen 1.3 millones de líneas. sed es muy lento en esto.