У меня есть файл, который содержит несколько тысяч номеров, каждое в своей строке:
34
42
11
6
2
99
...
Я ищу написать скрипт, который будет печатать сумму всех чисел в файле. У меня есть решение, но оно не очень эффективно. (Запуск занимает несколько минут.) Я ищу более эффективное решение. Какие-либо предложения?
awk
иbc
). Все они закончили добавлять миллион чисел менее чем за 10 секунд. Взгляните на них и посмотрите, как это можно сделать в чистой оболочке.Ответы:
Для однострочника Perl это в основном то же самое, что и
awk
решение в ответе Аймана Хури :Если вам интересно, что делают однострочники Perl, вы можете отменить их:
В результате получается более подробная версия программы в форме, которую никто никогда не написал бы самостоятельно:
Просто для хихиканья, я попробовал это с файлом, содержащим 1 000 000 номеров (в диапазоне 0 - 9 999). На моем Mac Pro он возвращается практически мгновенно. Это очень плохо, потому что я надеялся, что использование
mmap
будет очень быстрым, но это в то же время:источник
while { }
цикл вокруг вашей программы. Если вы положили} ... {
внутрь, то у вас естьwhile { } ... { }
. Злой? Слегка.-MO=Deparse
опции! Хотя бы по отдельной теме.Вы можете использовать awk:
источник
-F '\t'
опцией, если ваши поля содержат пробелы и разделены вкладками.Ни одно из решений до сих пор не используется
paste
. Вот один из них:В качестве примера вычислим Σn, где 1 <= n <= 100000:
(Для любопытных, вывел
seq n
бы последовательность чисел от1
доn
заданного положительного числаn
.)источник
seq 100000 | paste -sd+ - | bc -l
на Mac OS X Bash. И это, безусловно, самое сладкое и самое необычное решение!Просто для интереса давайте проверим это:
Я прервал Sed Run через 5 минут
Я нырял в Luaи это быстро
и пока я обновляю это, ruby:
Прислушайтесь к совету Эда Мортона: используя
$1
против использования
$0
источник
tr
решению.$0
вместо,$1
так как awk выполняет разбиение поля (что, очевидно, занимает время), если какое-либо поле специально упоминается в сценарии, но не иначе.Другой вариант заключается в использовании
jq
:-s
(--slurp
) читает строки ввода в массив.источник
Это прямо Bash:
источник
Вот еще один вкладыш
Это предполагает, что числа являются целыми числами. Если вам нужны десятичные дроби, попробуйте
Отрегулируйте 2 до необходимого количества десятичных знаков.
источник
Я предпочитаю использовать GNU datamash для таких задач, потому что он более краткий и разборчивый, чем perl или awk. Например
где 1 обозначает первый столбец данных.
источник
источник
Я предпочитаю использовать R для этого:
источник
(так же, как ответ Брайана Д. Фоя, без «КОНЦА»)
источник
perl -MO=Deparse
чтобы увидеть, как Perl анализирует программу. или документы для perlrun : perldoc.perl.org/perlrun.html (поиск -n). Perl переносит ваш код с помощью {}, если вы используете -n, чтобы он стал полноценной программой.Более кратко:
источник
time python -c "print(sum([float(s) for s in open('random_numbers','r')]))"
Perl 6
источник
Просто для удовольствия, давайте сделаем это с PDL , математическим движком Perl!
rcols
считывает столбцы в матрицу (в данном случае 1D) иsum
(неожиданно) суммирует все элементы матрицы.источник
Вот решение с использованием Python с выражением генератора. Протестировано с миллионами номеров на моем старом сыром ноутбуке.
источник
map()
:map(float, sys.stdin)
Я не мог просто пройти мимо ... Вот мой лайнер на Хаскеле. Это на самом деле вполне читабельно:
К сожалению, его нельзя
ghci -e
просто запустить, поэтому для него нужна основная функция, печать и компиляция.Для уточнения, мы читаем весь вход (
getContents
), разделить егоlines
,read
как числа иsum
.<$>
isfmap
оператор - мы используем его вместо обычного приложения функции, потому что уверен, что все это происходит в IO.read
нужно дополнительноеfmap
, потому что оно тоже есть в списке.Вот странное обновление, чтобы оно работало с поплавками:
источник
источник
Запуск R скриптов
Я написал R-скрипт для получения аргументов имени файла и суммирования строк.
Это можно ускорить с помощью пакета «data.table» или «vroom» следующим образом:
Бенчмаркинг
Те же данные бенчмаркинга, что и у @glenn jackman .
По сравнению с приведенным выше вызовом R запуск R 3.5.0 в качестве сценария сопоставим с другими методами (на том же сервере Linux Debian).
R скрипт с readLines
R скрипт с data.table
R скрипт с vroom
Сравнение с другими языками
Для справки здесь, как некоторые другие методы, предложенные на том же оборудовании
Python 2 (2.7.13)
Python 3 (3.6.8)
Рубин (2.3.3)
Perl (5.24.1)
Awk (4.1.4)
C (clang версия 3.3; gcc (Debian 6.3.0-18) 6.3.0)
Обновление с дополнительными языками
Луа (5.3.5)
tr (8.26) должен быть рассчитан в bash, несовместим с zsh
sed (4.4) должен быть рассчитан в bash, несовместим с zsh
примечание: кажется, что вызовы sed работают быстрее в системах с большим объемом доступной памяти (обратите внимание на меньшие наборы данных, используемые для тестирования sed)
Юлия (0.5.0)
Обратите внимание, что, как и в R, методы файлового ввода-вывода имеют разную производительность.
источник
C ++ "однострочник":
источник
Еще один для развлечения
или только другой удар
Но решение awk, вероятно, лучше, поскольку оно наиболее компактно.
источник
С всегда побеждает по скорости:
Время для чисел 1М (та же машина / вход, что и у моего ответа на Python):
источник
С рубином:
источник
ruby -e'p readlines.map(&:to_f).reduce(:+)'
.Я не знаю, сможете ли вы стать намного лучше, чем это, учитывая, что вам нужно прочитать весь файл.
источник
$_
переменная по умолчанию. Оператор ввода строки,<>
по умолчанию помещает свой результат туда, когда вы используете<>
вwhile
.$_
это переменная темы - она работает как 'it'. В этом случае<>
присваивает ему каждую строку. Он используется во многих местах, чтобы уменьшить беспорядок в коде и помочь с написанием однострочников. Сценарий говорит: «Установите сумму на 0, прочитайте каждую строку и добавьте ее к сумме, затем напечатайте сумму».$sum
. Поскольку это так просто, вы даже можете использовать модификатор оператораwhile
:$sum += $_ while <>; print $sum;
Я не проверял это, но это должно работать:
Возможно, вам придется добавить «\ n» в строку перед bc (например, через echo), если bc не обрабатывает EOF и EOL ...
источник
bc
выдает синтаксическую ошибку из-за завершающего "+" и отсутствия новой строки в конце. Это сработает и исключит бесполезное использованиеcat
:{ tr "\n" "+" | sed 's/+$/\n/'| bc; } < numbers2.txt
или<numbers2.txt tr "\n" "+" | sed 's/+$/\n/'| bc
tr "\n" "+" <file | sed 's/+$/\n/' | bc
Вот еще один:
источник
Вы можете сделать это с помощью Alacon - утилиты командной строки для базы данных Alasql .
Он работает с Node.js, поэтому вам нужно установить Node.js а затем пакет Alasql :
Для расчета суммы из файла TXT вы можете использовать следующую команду:
источник
Не проще заменить все новые строки на
+
, добавить0
и отправить ихRuby
интерпретатору?Если у вас его нет
irb
, вы можете отправить его на адресbc
, но вы должны удалить все новые строки, кроме последнего (изecho
). Лучше использоватьtr
для этого, если у вас нет докторской степениsed
.источник
На ходу:
источник
Баш вариант
источник
В оболочке, использующей awk, я использовал приведенный ниже скрипт для этого:
источник