Eu tenho um arquivo de texto com 2 milhões de linhas. Cada linha tem um número inteiro positivo. Estou tentando formar um tipo de tabela de frequências.
Arquivo de entrada:
3
4
5
8
A saída deve ser:
3
7
12
20
Como faço para fazer isso?
command-line
text-processing
Monty Harder
fonte
fonte
Respostas:
Com
awk
:$0
é a linha atual. Portanto, para cada linha, eu adiciono aototal
, defino a linha como novatotal
e, em seguida, o final1
é um atalho inativo - ele imprime a linha atual para todas as condições verdadeiras e1
como uma condição é avaliada como verdadeira.fonte
print
também pode ser usada?print total}
vez de$0 = total}1
{print(total += $0)}
Em um script python:
Usar
add_last.py
Execute-o com o arquivo de origem e o arquivo de saída direcionado como argumentos:
Explicação
O código é bastante legível, mas em detalhes:
Abrir arquivo de saída para gravar resultados
Arquivo de entrada aberto para leitura por linha
Leia as linhas, adicionando o valor da nova linha ao total:
Escreva o resultado no arquivo de saída:
fonte
Apenas por diversão
Isso funciona de forma pendente
+p
para cada linha da entrada e depois passa o resultado para adc
calculadora ondeentão
O
-e0
argumento entra0
nadc
pilha para inicializar a soma.fonte
real 0m4.234s
No Bash:
fonte
real 0m53.116s
, quase um minuto, em 1,3 milhões de linhas :)Para imprimir somas parciais de números inteiros fornecidas na entrada padrão, uma por linha:
Exemplo executável .
Se por algum motivo o comando for muito lento; você poderia usar o programa C:
Para criar e executar, digite:
Exemplo executável .
UINTMAX_MAX
é18446744073709551615
.O código C é várias vezes mais rápido que o comando awk na minha máquina para o arquivo de entrada gerado por:
fonte
accumulate()
itertoolVocê provavelmente quer algo assim:
Explicação do comando:
sort -n <filename> | uniq -c
classifica a entrada e retorna uma tabela de frequência| awk 'BEGIN{print "Number\tFrequency"}{print $2"\t"$1}'
transforma a saída em um formato melhorExemplo:
Arquivo de Entrada
list.txt
:O comando:
fonte
Você pode fazer isso no vim. Abra o arquivo e digite as seguintes teclas:
Observe que
<C-a>
na verdade é ctrl-a e<cr>
é retorno de carro , ou seja, o botão Enter.Veja como isso funciona. Primeiro, queremos limpar o registro 'a' para que não tenha efeitos colaterais na primeira vez. Isto é simplesmente
qaq
. Em seguida, fazemos o seguinte:Depois que a macro recursiva termina, chamamos simplesmente
:wq<cr>
para salvar e sair.fonte
One-liner Perl:
Com 2,5 milhões de linhas de números, leva cerca de 6,6 segundos para processar:
fonte
real 0m0.908s
, até legal.Uma linha simples do Bash:
x
é a soma acumulada de todos os números da linha atual e acima.n
é o número na linha atual.Passamos por todas as linhas
n
deINPUT_FILE
e adicionamos seu valor numérico à nossa variávelx
e imprimimos essa soma durante cada iteração.O Bash é um pouco lento aqui, porém, você pode esperar que isso seja executado em torno de 20 a 30 segundos para um arquivo com 2 milhões de entradas, sem imprimir a saída no console (que é ainda mais lenta, independentemente do método usado).
fonte
Semelhante à resposta do @ steeldriver, mas com o pouco menos misterioso
bc
:O bom de
bc
(edc
) é que elas são calculadoras de precisão arbitrárias, portanto nunca transbordarão ou sofrerão falta de precisão sobre números inteiros.A
sed
expressão transforma a entrada em:Isso é então avaliado por
bc
. Aa
variável bc é inicializada automaticamente em 0. Cada linha é incrementadaa
e a imprime explicitamente.fonte
real 0m5.642s
em 1,3 milhões de linhas. sed é realmente lento nisso.