Tengo un archivo que contiene varios miles de números, cada uno en su propia línea:
34
42
11
6
2
99
...
Estoy buscando escribir un script que imprima la suma de todos los números en el archivo. Tengo una solución, pero no es muy eficiente. (Tarda varios minutos en ejecutarse). Estoy buscando una solución más eficiente. ¿Alguna sugerencia?
awk
ybc
). Todo esto terminó de sumar un millón de números en menos de 10 segundos. Eche un vistazo a esos y vea cómo se puede hacer en shell puro.Respuestas:
Para una línea de Perl, es básicamente lo mismo que la
awk
solución en la respuesta de Ayman Hourieh :Si tienes curiosidad por saber qué hacen las frases de Perl, puedes eliminarlas:
El resultado es una versión más detallada del programa, en una forma que nadie escribiría por sí solo:
Solo por risas, probé esto con un archivo que contiene 1,000,000 de números (en el rango de 0 a 9,999). En mi Mac Pro, regresa casi instantáneamente. Eso es una lástima, porque esperaba que usarlo
mmap
fuera realmente rápido, pero es al mismo tiempo:fuente
while { }
ciclo alrededor de su programa. Si pones} ... {
dentro, entonces tieneswhile { } ... { }
. ¿Mal? Ligeramente.-MO=Deparse
opción! Aunque sobre un tema aparte.Puedes usar awk:
fuente
-F '\t'
opción si sus campos contienen espacios y están separados por pestañas.Ninguna de las soluciones hasta ahora se utiliza
paste
. Aquí hay uno:Como ejemplo, calcule Σn donde 1 <= n <= 100000:
(Para los curiosos,
seq n
imprimiría una secuencia de números de1
an
dado un número positivon
).fuente
seq 100000 | paste -sd+ - | bc -l
en el shell de Mac OS X Bash. ¡Y esta es, con mucho, la solución más dulce y única!Solo por diversión, vamos a compararlo:
Aborté la carrera sed después de 5 minutos
He estado buceando a lua, y es rápido:
y mientras estoy actualizando esto, ruby:
Preste atención al consejo de Ed Morton: usar
$1
vs usar
$0
fuente
tr
solución.$0
lugar de hacerlo,$1
ya que awk divide los campos (lo que obviamente lleva tiempo) si algún campo se menciona específicamente en el script pero no lo hace de otra manera.Otra opción es usar
jq
:-s
(--slurp
) lee las líneas de entrada en una matriz.fuente
Esto es directamente Bash:
fuente
Aquí hay otra línea
Esto supone que los números son enteros. Si necesita decimales, intente
Ajuste 2 a la cantidad de decimales necesarios.
fuente
Prefiero usar GNU Datamash para tales tareas porque es más sucinto y legible que perl o awk. Por ejemplo
donde 1 denota la primera columna de datos.
fuente
fuente
Prefiero usar R para esto:
fuente
(igual que la respuesta de brian d foy, sin 'FIN')
fuente
perl -MO=Deparse
para ver cómo Perl analiza el programa. o los documentos para perlrun: perldoc.perl.org/perlrun.html (busque -n). perl envuelve su código con {} si usa -n para que se convierta en un programa completo.Más sucinto:
fuente
time python -c "print(sum([float(s) for s in open('random_numbers','r')]))"
Perl 6
fuente
¡Solo por diversión, hagámoslo con PDL , el motor matemático de matriz de Perl!
rcols
lee columnas en una matriz (1D en este caso) ysum
(sorpresa) suma todo el elemento de la matriz.fuente
Aquí hay una solución usando python con una expresión generadora. Probado con un millón de números en mi vieja computadora portátil.
fuente
map()
:map(float, sys.stdin)
No podría simplemente pasar ... Aquí está mi frase de Haskell. En realidad es bastante legible:
Desafortunadamente, no hay
ghci -e
que ejecutarlo, por lo que necesita la función principal, impresión y compilación.Para aclarar, leemos la entrada completa (
getContents
), la dividimos porlines
,read
como números ysum
.<$>
esfmap
operador: lo usamos en lugar de la aplicación de función habitual porque seguro que todo esto sucede en IO.read
necesita un adicionalfmap
, porque también está en la lista.Aquí hay una actualización extraña para que funcione con flotadores:
fuente
fuente
Ejecutar scripts R
He escrito un script R para tomar argumentos de un nombre de archivo y sumar las líneas.
Esto se puede acelerar con el paquete "data.table" o "vroom" de la siguiente manera:
Benchmarking
Los mismos datos de evaluación comparativa que @glenn jackman .
En comparación con la llamada R anterior, ejecutar R 3.5.0 como script es comparable a otros métodos (en el mismo servidor Linux Debian).
R script con readLines
R script con data.table
R script con vroom
Comparación con otros idiomas.
Para referencia aquí como algunos otros métodos sugeridos en el mismo hardware
Python 2 (2.7.13)
Python 3 (3.6.8)
Rubí (2.3.3)
Perl (5.24.1)
Awk (4.1.4)
C (clang versión 3.3; gcc (Debian 6.3.0-18) 6.3.0)
Actualización con idiomas adicionales
Lua (5.3.5)
tr (8.26) debe cronometrarse en bash, no es compatible con zsh
sed (4.4) debe cronometrarse en bash, no es compatible con zsh
nota: las llamadas sed parecen funcionar más rápido en sistemas con más memoria disponible (tenga en cuenta los conjuntos de datos más pequeños utilizados para la evaluación comparativa de sed)
Julia (0.5.0)
Observe que, como en R, los métodos de E / S de archivo tienen un rendimiento diferente.
fuente
C ++ "one-liner":
fuente
Otro para divertirse
u otra fiesta solamente
Pero la solución awk es probablemente la mejor, ya que es más compacta.
fuente
C siempre gana por velocidad:
Tiempo para números 1M (la misma máquina / entrada que mi respuesta de Python):
fuente
Con Ruby:
fuente
ruby -e'p readlines.map(&:to_f).reduce(:+)'
.No sé si puede ser mucho mejor que esto, considerando que necesita leer todo el archivo.
fuente
$_
es la variable por defecto. El operador de entrada de línea,<>
, pone de resultado en que hay por defecto cuando se utilizan<>
enwhile
.$_
es la variable de tema: funciona como el 'it'. En este caso, le<>
asigna cada línea. Se utiliza en varios lugares para reducir el desorden de código y ayudar a escribir frases ingeniosas. El script dice "Establezca la suma en 0, lea cada línea y agréguela a la suma, luego imprima la suma".$sum
. Como esto es tan simple, incluso puede usar un modificador de declaraciónwhile
:$sum += $_ while <>; print $sum;
No he probado esto pero debería funcionar:
Puede que tenga que agregar "\ n" a la cadena antes de bc (como a través de echo) si bc no trata EOF y EOL ...
fuente
bc
emite un error de sintaxis debido al "+" final y la falta de nueva línea al final. Esto funcionará y elimina el uso inútil decat
:{ tr "\n" "+" | sed 's/+$/\n/'| bc; } < numbers2.txt
o<numbers2.txt tr "\n" "+" | sed 's/+$/\n/'| bc
tr "\n" "+" <file | sed 's/+$/\n/' | bc
Aquí está otro:
fuente
Puede hacerlo con Alacon - utilidad de línea de comandos para la base de datos Alasql .
Funciona con Node.js, por lo que debe instalar Node.js y luego el paquete Alasql :
Para calcular la suma del archivo TXT puede usar el siguiente comando:
fuente
¿No es más fácil reemplazar todas las líneas nuevas
+
, agregar una0
y enviarla alRuby
intérprete?Si no lo tiene
irb
, puede enviarlo abc
, pero debe eliminar todas las líneas nuevas excepto la última (deecho
). Es mejor usarlotr
para esto, a menos que tenga un doctoradosed
.fuente
En Go:
fuente
Variante Bash
fuente
En shell usando awk, he usado el siguiente script para hacerlo:
fuente