Comment puis-je rapidement la somme de tous les nombres dans un fichier?
J'ai un fichier qui contient plusieurs milliers de numéros, chacun sur sa propre ligne:
34
42
11
6
2
99
...
Je suis à la recherche d'écrire un script qui permet d'imprimer la somme de tous les nombres dans le fichier. J'ai une solution, mais ce n'est pas très efficace. (Il faut plusieurs minutes pour s'exécuter.) Je suis à la recherche d'une solution plus efficace. Des suggestions?
- Quelle a été votre lente de la solution? Peut-être nous pouvons vous aider à comprendre ce qui est lent à ce sujet. 🙂
- d foy, je suis trop gênée pour le poster. Je sais pourquoi c'est lent. C'est parce que j'appelle "le chat de nom de fichier | head-n 1" pour obtenir le plus grand nombre, l'ajouter à un total en cours d'exécution, et de l'appeler "chat de nom de fichier | queue..." pour supprimer la ligne supérieure pour l'itération suivante... j'ai beaucoup à apprendre sur la programmation!!!
- C'est...très systématique. Très clair et simple, et je l'aime pour tout ce qu'il est horrible abomination. Construit, je suppose, sur les outils que vous le saviez quand vous avez commencé, à droite?
- complet double: stackoverflow.com/questions/450799/...
- Il a dû vous prendre un long moment pour cela. C'est un très couperet de la résolution de problème technique, et oh si mal. Il ressemble à un cas classique de réfléchir. Plusieurs de Glen Jackman les solutions de création de scripts shell solutions (et les deux sont de la pure shell qui n'utilisent pas les choses comme
awk
etbc
). Ces tous terminé l'ajout d'un millions de numéros en moins de 10 secondes. Jetez un oeil à ceux et de voir comment il peut être fait dans le plus pur shell. - Mark Roberts 1place, stackoverflow.com/a/18380369/4592448 )))
Vous devez vous connecter pour publier un commentaire.
Pour Perl one-liner, c'est en gros la même chose que le
awk
solution dans Ayman Hourieh réponse:Si vous êtes curieux de savoir ce que Perl one-liners de le faire, vous pouvez deparse eux:
Le résultat est une version plus détaillée du programme, sous une forme que personne n'aurait jamais d'écrire sur leur propre:
Juste pour rire, j'ai essayé avec un fichier contenant 1 000 000 de numéros (dans la plage de 0 à 9 999 habitants). Sur mon Mac Pro, il renvoie presque instantanément. C'est dommage, parce que j'espérais à l'aide de
mmap
serait vraiment rapide, mais c'est juste le même temps:while { }
boucle autour de votre programme. Si vous mettez} ... {
à l'intérieur, alors vous avezwhile { } ... { }
. Le mal? Légèrement.-MO=Deparse
option! Même si sur un sujet distinct.perl -nle '$sum += $_; print $sum} END {'
Vous pouvez utiliser awk:
-F '\t'
option si vos champs contiennent des espaces et sont séparés par des tabulations.Aucune solution à ce jour l'utilisation
paste
. En voici un:Comme un exemple, calculer Σn où 1<=n<=100000:
(Pour les curieux,
seq n
serait d'imprimer une séquence de nombres à partir de1
àn
donné un nombre positifn
.)seq 100000 | paste -sd+ - | bc -l
sur Mac OS X Bash. Et c'est de loin le plus doux et le unixest solution!Juste pour le plaisir, nous allons comparer:
J'ai abandonné la sed courir après 5 minutes
J'ai été plongée à lua, et il est rapide:
et alors que je suis à jour de cette, ruby:
Garde Ed Morton conseils: à l'aide de
$1
vs l'aide de
$0
tr
solution.$0
au lieu de$1
depuis awk n'domaine de fractionnement (qui, évidemment, prend du temps), si un champ est spécifiquement mentionné dans le script, mais il n'a pas le contraire.Une autre option est d'utiliser
jq
:-s
(--slurp
) lit les lignes d'entrée dans un tableau.C'est tout droit Bash:
Voici un autre one-liner
Cela suppose que les nombres sont des entiers. Si vous avez besoin de décimales, essayez
Ajuster 2 pour le nombre de décimales nécessaires.
Je préfère utiliser R pour les ce:
Je préfère utiliser GNU datamash pour de telles tâches, car il est plus concis et lisible que perl ou awk. Par exemple
où 1 désigne la première colonne de données.
(le même que brian d foy de réponse, sans "FIN")
Juste pour le plaisir, permet de le faire avec PDL, Perl tableau de mathématiques moteur!
rcols
lit à colonnes dans une matrice (1D dans ce cas) etsum
(surprise) sommes tous les éléments de la matrice.Voici une solution à l'aide de python avec un générateur d'expression. Testé avec un million de numéros sur mon ancien cruddy ordinateur portable.
map()
:map(float, sys.stdin)
Perl 6
Succincte:
Je n'ai pas testé mais cela devrait fonctionner:
Vous pourriez avoir à ajouter "\n" à la chaîne avant de la colombie-britannique (comme par écho) si colombie-britannique ne permet pas de traiter des expressions du FOLKLORE et EOL...
bc
émet une erreur de syntaxe en raison de la fin "+" et l'absence de saut de ligne à la fin. Ce sera le travail et élimine ainsi inutile l'utilisation 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
Un autre pour le plaisir
ou d'une autre bash seulement
Mais awk solution est préférable car il est plus compact.
Avec Ruby:
ruby -e'p readlines.map(&:to_f).reduce(:+)'
.L'exécution de la R scripts
J'ai écrit un script R pour prendre des arguments d'un nom de fichier et la somme des lignes.
Cela peut être accéléré avec les données".le tableau" ou "vroom" paquet comme suit:
Analyse comparative
Même les données d'analyse comparative comme @glenn jackman.
En comparaison à la R l'appel ci-dessus, l'exécution de la R 3.5.0 qu'un script est comparable à d'autres méthodes (sur le même serveur Linux Debian).
Script R avec readLines
Script R avec les données.tableau
Script R avec vroom
Comparaison avec d'autres langues
Pour référence ici que quelques autres méthodes proposées sur le même matériel
Python 2 (2.7.13)
Python 3 (3.6.8)
Ruby (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 )
Mise à jour avec d'autres langues
Lua (5.3.5)
tr (8.26) doit être programmé dans bash, pas compatible avec zsh
sed (4.4) doit être programmé dans bash, pas compatible avec zsh
remarque: sed appels semblent travailler plus rapidement sur des systèmes avec plus de mémoire disponible (note de plus petits ensembles de données utilisés pour l'analyse comparative sed)
Julia (0.5.0)
Avis que, comme dans R, e/S de fichier méthodes ont des performances différentes.
Je ne pourrais pas simplement passer par... Voici mon Haskell one-liner. C'est en fait tout à fait lisible:
Malheureusement il n'y a pas de
ghci -e
de l'exécuter, donc il faut que la fonction principale, d'impression et de compilation.Pour clarifier, nous avons lu ensemble de l'entrée (getContents), divisé en lignes, lire des nombres et de la somme.
<$>
est fmap opérateur - nous de l'utiliser au lieu de l'habituel fonction de l'application, car sûr tout cela se fait dans les IO.read
besoin d'un autre fmap, parce que c'est aussi dans la liste.Voici une étrange mise à niveau pour le faire fonctionner avec des flotteurs:
Je ne sais pas si vous pouvez obtenir beaucoup mieux que cela, en considérant que vous avez besoin de lire le fichier en entier.
$_
est la variable par défaut. L'entrée ligne de l'opérateur,<>
, le met, le résultat d'il y a par défaut lorsque vous utilisez<>
danswhile
.<>
attribue à chaque ligne pour elle. Il est utilisé dans un certain nombre de lieux pour réduire l'encombrement de code et d'aide à la rédaction d'un seul-liners. Le script dit "Mis à la somme de 0, de lire chaque ligne et l'ajouter à la somme, puis imprimez la somme."$sum
. Puisque c'est si simple, vous pouvez même utiliser une déclaration modificateurwhile
:$sum += $_ while <>; print $sum;
Voici un autre:
C gagne toujours pour la vitesse:
Timing pour 1M numéros (même machine/de l'entrée de mon python réponse):
Vous pouvez le faire avec Alacon - utilitaire de ligne de commande pour Alasql base de données.
Il fonctionne avec Node.js, si vous avez besoin d'installer Node.js et puis Alasql package:
Pour calculer la somme à partir d'un fichier TXT vous pouvez utiliser la commande suivante:
Il n'est pas plus facile à remplacer toutes les nouvelles lignes par
+
, ajouter un0
et l'envoyer à l'Ruby
interprète?Si vous n'avez pas
irb
, vous pouvez l'envoyer àbc
, mais vous devez supprimer tous les retours à la ligne, sauf la dernière (deecho
). Il est préférable d'utilisertr
pour cela, sauf si vous avez un Doctorat ensed
.Juste pour être ridicule: