J'ai un fichier qui contient plusieurs milliers de numéros, chacun sur sa propre ligne:
34
42
11
6
2
99
...
Je cherche à écrire un script qui imprimera la somme de tous les nombres du fichier. J'ai une solution, mais elle n'est pas très efficace. (Cela prend plusieurs minutes.) Je recherche une solution plus efficace. Aucune suggestion?
awk
etbc
). Ils ont tous fini d'ajouter un million de numéros en moins de 10 secondes. Jetez un oeil à ceux-ci et voyez comment cela peut être fait en pure coque.Réponses:
Pour un monoplace Perl, c'est essentiellement la même chose que la
awk
solution dans la réponse d'Ayman Hourieh :Si vous êtes curieux de savoir ce que font les monolignes Perl, vous pouvez les analyser:
Le résultat est une version plus verbeuse du programme, sous une forme que personne n'écrirait jamais seul:
Juste pour rire, j'ai essayé cela avec un fichier contenant 1 000 000 de numéros (compris entre 0 et 9 999). Sur mon Mac Pro, il revient pratiquement instantanément. C'est dommage, car j'espérais que l'utilisation
mmap
serait très rapide, mais c'est juste en même temps:la source
while { }
boucle autour de votre programme. Si vous mettez à l'} ... {
intérieur, alors vous l'avezwhile { } ... { }
. Mal? Légèrement.-MO=Deparse
option! Même si sur un sujet distinct.Vous pouvez utiliser awk:
la source
-F '\t'
option si vos champs contiennent des espaces et sont séparés par des tabulations.Aucune solution n'a été utilisée jusqu'à présent
paste
. En voici un:Par exemple, calculez Σn où 1 <= n <= 100000:
(Pour les curieux,
seq n
imprimerait une séquence de nombres de1
àn
donné un nombre positifn
.)la source
seq 100000 | paste -sd+ - | bc -l
sur le shell Mac OS X Bash. Et c'est de loin la solution la plus douce et la plus unix!Juste pour le plaisir, comparons-le:
J'ai abandonné la course sed après 5 minutes
J'ai plongé lua, et c'est rapide:
et pendant que je mets à jour ça, ruby:
Tenez compte des conseils d'Ed Morton: utiliser
$1
vs utiliser
$0
la source
tr
solution.$0
au lieu de,$1
car awk divise les champs (ce qui prend évidemment du temps) si un champ est spécifiquement mentionné dans le script mais ne le fait pas autrement.Une autre option consiste à utiliser
jq
:-s
(--slurp
) lit les lignes d'entrée dans un tableau.la source
C'est tout simplement Bash:
la source
Voici un autre doublure
Cela suppose que les nombres sont des nombres entiers. Si vous avez besoin de décimales, essayez
Ajustez 2 au nombre de décimales nécessaires.
la source
Je préfère utiliser le datamash GNU pour de telles tâches car il est plus succinct et lisible que perl ou awk. Par exemple
où 1 désigne la première colonne de données.
la source
la source
Je préfère utiliser R pour cela:
la source
(identique à la réponse de brian d foy, sans 'END')
la source
perl -MO=Deparse
pour voir comment perl analyse le programme. ou les documents pour perlrun: perldoc.perl.org/perlrun.html (recherchez -n). perl enveloppe votre code avec {} si vous utilisez -n pour qu'il devienne un programme complet.Plus succinct:
la source
time python -c "print(sum([float(s) for s in open('random_numbers','r')]))"
Perl 6
la source
Juste pour le plaisir, faisons-le avec PDL , le moteur mathématique de Perl!
rcols
lit les colonnes dans une matrice (1D dans ce cas) etsum
(surprise) additionne tous les éléments de la matrice.la source
Voici une solution utilisant python avec une expression de générateur. Testé avec un million de numéros sur mon vieux portable cruddy.
la source
map()
:map(float, sys.stdin)
Je ne pouvais pas simplement passer ... Voici mon one-liner Haskell. C'est en fait assez lisible:
Malheureusement, il n'y a pas
ghci -e
à l'exécuter, il a donc besoin de la fonction principale, de l'impression et de la compilation.Pour clarifier, nous lisons l'intégralité de input (
getContents
), divisé parlines
,read
sous forme de nombres etsum
.<$>
estfmap
opérateur - nous l'utilisons à la place de l'application de fonction habituelle car bien sûr, tout cela se produit dans IO.read
a besoin d'un supplémentfmap
, car il est également dans la liste.Voici une étrange mise à niveau pour le faire fonctionner avec des flotteurs:
la source
la source
Exécution de scripts R
J'ai écrit un script R pour prendre les arguments d'un nom de fichier et additionner les lignes.
Cela peut être accéléré avec le package "data.table" ou "vroom" comme suit:
Analyse comparative
Mêmes données d'analyse comparative que @glenn jackman .
Par rapport à l'appel R ci-dessus, exécuter R 3.5.0 en tant que script est comparable à d'autres méthodes (sur le même serveur Linux Debian).
Script R avec readLines
Script R avec data.table
Script R avec vroom
Comparaison avec d'autres langues
Pour référence ici, comme d'autres méthodes suggérées sur le même matériel
Python 2 (2.7.13)
Python 3 (3.6.8)
Rubis (2.3.3)
Perl (5.24.1)
Awk (4.1.4)
C (clang version 3.3; gcc (Debian 6.3.0-18) 6.3.0)
Mettre à jour avec des langues supplémentaires
Lua (5.3.5)
tr (8.26) doit être chronométré en bash, non compatible avec zsh
sed (4.4) doit être chronométré en bash, non compatible avec zsh
note: les appels sed semblent fonctionner plus rapidement sur les systèmes avec plus de mémoire disponible (notez les petits ensembles de données utilisés pour comparer sed)
Julia (0.5.0)
Notez que comme dans R, les méthodes d'E / S de fichiers ont des performances différentes.
la source
C ++ "one-liner":
la source
Un autre pour le plaisir
ou un autre bash seulement
Mais la solution awk est probablement la meilleure car elle est la plus compacte.
la source
C gagne toujours pour la vitesse:
Timing pour les nombres 1M (même machine / entrée que ma réponse python):
la source
Avec Ruby:
la source
ruby -e'p readlines.map(&:to_f).reduce(:+)'
.Je ne sais pas si vous pouvez obtenir beaucoup mieux que cela, étant donné que vous devez lire l'intégralité du fichier.
la source
$_
est la variable par défaut. L'opérateur d'entrée de ligne,<>
, met son résultat là - dedans par défaut lorsque vous utilisez<>
danswhile
.$_
est la variable de sujet - elle fonctionne comme le «il». Dans ce cas,<>
lui assigne chaque ligne. Il est utilisé à plusieurs endroits pour réduire l'encombrement du code et aider à l'écriture de lignes simples. Le script dit "Réglez la somme à 0, lisez chaque ligne et ajoutez-la à la somme, puis imprimez la somme."$sum
. Comme c'est si simple, vous pouvez même utiliser un modificateur d'instructionwhile
:$sum += $_ while <>; print $sum;
Je n'ai pas testé cela mais ça devrait marcher:
Vous devrez peut-être ajouter "\ n" à la chaîne avant bc (comme via echo) si bc ne traite pas EOF et EOL ...
la source
bc
émet une erreur de syntaxe à cause du "+" de fin et du manque de nouvelle ligne à la fin. Cela fonctionnera et éliminera une utilisation inutile 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
En voici une autre:
la source
Vous pouvez le faire avec Alacon - utilitaire de ligne de commande pour Alasql base de données .
Cela fonctionne avec Node.js, vous devez donc installer Node.js puis Alasql package :
Pour calculer la somme à partir du fichier TXT, vous pouvez utiliser la commande suivante:
la source
Il n'est pas plus facile de remplacer toutes les nouvelles lignes par
+
, d'ajouter un0
et de l'envoyer à l'Ruby
interpréteur?Si vous n'en avez pas
irb
, vous pouvez l'envoyer àbc
, mais vous devez supprimer toutes les nouvelles lignes sauf la dernière (deecho
). Il est préférable de l'utilisertr
pour cela, sauf si vous avez un doctoratsed
.la source
In Go:
la source
Variante bash
la source
En shell utilisant awk, j'ai utilisé le script ci-dessous pour le faire:
la source