Eu tenho um arquivo que contém vários milhares de números, cada um em sua própria linha:
34
42
11
6
2
99
...
Estou procurando escrever um script que imprima a soma de todos os números no arquivo. Eu tenho uma solução, mas não é muito eficiente. (Demora alguns minutos para ser executado.) Estou procurando uma solução mais eficiente. Alguma sugestão?
awk
ebc
). Todos terminaram adicionando um milhão de números em menos de 10 segundos. Dê uma olhada nelas e veja como isso pode ser feito com casca pura.Respostas:
Para uma linha única de Perl, é basicamente a mesma coisa que a
awk
solução na resposta de Ayman Hourieh :Se você estiver curioso sobre o que as linhas de uma linha do Perl fazem, você pode separá-las:
O resultado é uma versão mais detalhada do programa, de uma forma que ninguém jamais escreveria por conta própria:
Apenas para rir, tentei isso com um arquivo contendo 1.000.000 de números (no intervalo de 0 a 9.999). No meu Mac Pro, ele retorna virtualmente instantaneamente. Isso é muito ruim, porque eu esperava que o uso
mmap
fosse muito rápido, mas é exatamente ao mesmo tempo:fonte
while { }
loop ao redor do seu programa. Se você colocar} ... {
dentro, então você temwhile { } ... { }
. Mal? Levemente.-MO=Deparse
opção! Mesmo que em um tópico separado.Você pode usar o awk:
fonte
-F '\t'
opção se seus campos contêm espaços e são separados por tabulações.Até agora nenhuma das soluções é utilizada
paste
. Aqui está um:Como exemplo, calcule wheren onde 1 <= n <= 100000:
(Para os curiosos,
seq n
imprimiria uma sequência de números de1
paran
um número positivon
.)fonte
seq 100000 | paste -sd+ - | bc -l
no shell do Mac OS X Bash. E esta é de longe a solução mais doce e a mais unix!Apenas por diversão, vamos compará-lo:
Abortei a corrida após 5 minutos
Eu tenho mergulhado para luae é rápido:
e enquanto estou atualizando isso, ruby:
Preste atenção ao conselho de Ed Morton: usar
$1
vs usando
$0
fonte
tr
solução.$0
vez de o$1
awk dividir o campo (o que obviamente leva tempo) se algum campo for mencionado especificamente no script, mas não o fizer.Outra opção é usar
jq
:-s
(--slurp
) lê as linhas de entrada em uma matriz.fonte
Este é Bash direto:
fonte
Aqui está outra frase
Isso pressupõe que os números são inteiros. Se você precisar de casas decimais, tente
Ajuste 2 para o número de casas decimais necessárias.
fonte
Eu prefiro usar o GNU datamash para essas tarefas porque é mais sucinto e legível que o perl ou o awk. Por exemplo
onde 1 indica a primeira coluna de dados.
fonte
fonte
Eu prefiro usar R para isso:
fonte
(o mesmo que a resposta de brian d foy, sem 'END')
fonte
perl -MO=Deparse
para ver como o perl analisa o programa. ou os documentos para perlrun: perldoc.perl.org/perlrun.html (pesquise -n). O perl agrupa seu código com {} se você usar -n para que ele se torne um programa completo.Mais sucinto:
fonte
time python -c "print(sum([float(s) for s in open('random_numbers','r')]))"
Perl 6
fonte
Apenas por diversão, vamos fazê-lo com o PDL , o mecanismo matemático de matriz do Perl!
rcols
lê colunas em uma matriz (1D neste caso) esum
(surpresa) soma todo o elemento da matriz.fonte
Aqui está uma solução usando python com uma expressão de gerador. Testado com um milhão de números no meu laptop velho e sujo.
fonte
map()
:map(float, sys.stdin)
Eu não podia simplesmente passar por aqui ... Aqui está o meu verso de Haskell. Na verdade, é bastante legível:
Infelizmente, não há
ghci -e
como executá-lo, por isso ele precisa da função principal, impressão e compilação.Para esclarecer, lemos toda a entrada (
getContents
), dividimos porlines
,read
como números esum
.<$>
éfmap
operador - nós o usamos em vez da aplicação de função usual, porque com certeza isso tudo acontece no IO.read
precisa de um adicionalfmap
, porque também está na lista.Aqui está uma atualização estranha para fazê-lo funcionar com carros alegóricos:
fonte
fonte
Executando scripts R
Eu escrevi um script R para pegar argumentos de um nome de arquivo e somar as linhas.
Isso pode ser acelerado com o pacote "data.table" ou "vroom" da seguinte maneira:
avaliação comparativa
Os mesmos dados de benchmarking que @glenn jackman .
Em comparação com a chamada R acima, a execução do R 3.5.0 como um script é comparável a outros métodos (no mesmo servidor Debian Linux).
Script R com readLines
Script R com data.table
Script R com vroom
Comparação com outros idiomas
Para referência aqui, como alguns outros métodos sugeridos no mesmo hardware
Python 2 (2.7.13)
Python 3 (3.6.8)
Ruby (2.3.3)
Perl (5.24.1)
Awk (4.1.4)
C (versão clang 3.3; gcc (Debian 6.3.0-18) 6.3.0)
Atualizar com idiomas adicionais
Lua (5.3.5)
tr (8.26) deve ser cronometrado no bash, não compatível com zsh
sed (4.4) deve ser cronometrado no bash, não compatível com zsh
note: as chamadas sed parecem funcionar mais rapidamente em sistemas com mais memória disponível (observe conjuntos de dados menores usados para comparar o sed)
Julia (0.5.0)
Observe que, como no R, os métodos de E / S do arquivo têm desempenho diferente.
fonte
C ++ "one-liner":
fonte
Outro por diversão
ou apenas outra festança
Mas a solução awk é provavelmente a melhor, pois é mais compacta.
fonte
C sempre ganha por velocidade:
Tempo para números de 1 milhão (a mesma máquina / entrada que minha resposta em python):
fonte
Com Ruby:
fonte
ruby -e'p readlines.map(&:to_f).reduce(:+)'
.Não sei se você pode ficar muito melhor do que isso, considerando que precisa ler o arquivo inteiro.
fonte
$_
é a variável padrão. O operador de entrada de linha,<>
, coloca-o do resultado lá por padrão quando você usa<>
nowhile
.$_
é a variável de tópico - funciona como o 'it'. Nesse caso,<>
atribui cada linha a ela. Ele é usado em vários locais para reduzir a desordem de código e ajudar na escrita de linhas únicas. O script diz "Defina a soma como 0, leia cada linha e adicione-a à soma e depois imprima a soma".$sum
. Como isso é tão simples, você pode até usar um modificador de instruçãowhile
:$sum += $_ while <>; print $sum;
Eu não testei isso, mas deve funcionar:
Talvez você precise adicionar "\ n" à string antes de bc (como via eco) se bc não tratar EOF e EOL ...
fonte
bc
emite um erro de sintaxe devido ao "+" à direita e falta de nova linha no final. Isso funcionará e elimina o uso inútil decat
:{ tr "\n" "+" | sed 's/+$/\n/'| bc; } < numbers2.txt
ou<numbers2.txt tr "\n" "+" | sed 's/+$/\n/'| bc
tr "\n" "+" <file | sed 's/+$/\n/' | bc
Aqui está outro:
fonte
Você pode fazer isso com o Alacon - utilitário de linha de comando do banco de dados Alasql .
Funciona com o Node.js, então você precisa instalar o Node.js e o pacote Alasql :
Para calcular a soma do arquivo TXT, você pode usar o seguinte comando:
fonte
Não é mais fácil substituir todas as novas linhas
+
, adicionar a0
e enviá-lo aoRuby
intérprete?Se você não tiver
irb
, poderá enviá-lo parabc
, mas precisará remover todas as novas linhas, exceto a última (deecho
). É melhor usartr
isso, a menos que você tenha um doutoradosed
.fonte
Em Go:
fonte
Variante Bash
fonte
No shell usando o awk, usei o script abaixo para fazer isso:
fonte