Как я могу сгенерировать текущую совокупную сумму чисел в текстовом файле?

откройте терминал и в командной строке введите

du -sk * | sort -n

. Это даст вам список самых больших файлов или папок в порядке размера, причем самый большой внизу. Если папка особенно велика, cd в нее и повторите процесс.

1
задан 3 February 2017 в 03:04

9 ответов

В сценарии python:

#!/usr/bin/env python3
import sys

f = sys.argv[1]; out = sys.argv[2]

n = 0

with open(out, "wt") as wr:
    with open(f) as read:
        for l in read:
            n = n + int(l); wr.write(str(n)+"\n")

Использовать

Скопировать сценарий в пустой файл, сохранить его как add_last.py Запустить его с исходным файлом и целевым выходом файл в качестве аргументов:
python3 /path/to/add_last.py <input_file> <output_file>

Объяснение

Код довольно читабельен, но подробно:

Скопируйте сценарий в пустой файл, сохраните его как add_last.py Откройте файл ввода для чтения в строке
with open(f) as read:
    for l in read:
Запустите его с исходным файлом и целевым выходным файлом в качестве аргументов:
python3 /path/to/add_last.py <input_file> <output_file>

Запустите его с помощью исходный файл и целевой файл вывода в качестве аргументов:

wr.write(str(n)+"\n")
9
ответ дан 23 May 2018 в 01:51
  • 1
  • 2
    Речь идет не о сокращении времени или времени (миллионы строк - это не большие данные). Код в вашем ответе не является идиоматическим Python. Мой ответ - это скорее ваша питоническая версия. – jfs 3 February 2017 в 01:16
  • 3
    @ J.F.Sebastian, если более идиоматическая версия медленнее, почему кто-то предпочитает это? Нет ничего особенного в том, чтобы быть «питоническим». это просто соглашение, которое помогает разработчикам python совместно использовать код и стандарты для удобочитаемости. Если более идиоматическая версия менее эффективна (медленнее), то ее не следует использовать, если вы не работаете в среде, где стандартизация важнее производительности (что звучит как ужасная идея для меня). – terdon♦ 3 February 2017 в 12:55
  • 4
    @terdon есть что сказать о преждевременной оптимизации. Читаемость может быть важной из-за долгосрочной ремонтопригодности. – muru 3 February 2017 в 13:04
  • 5
    @muru конечно, но это прекрасно читаемо. Это только преступление не является «питоническим». Не говоря уже о том, что мы говорим о 7 строках кода, а не о каком-то гигантском проекте. Эффективность жертвоприношений во имя условностей стиля кажется неправильным. – terdon♦ 3 February 2017 в 13:10
Просто для удовольствия

$ sed 'a+p' file | dc -e0 -
3
7
12
20

Это работает путем добавления +p для каждой строки ввода, а затем передать результат в dc калькулятор где [ ! d2]

   +      Pops two values off the stack, adds them, and pushes the result.
          The precision of the result is determined only by the values  of
          the arguments, and is enough to be exact.

, то

   p      Prints  the  value on the top of the stack, without altering the
          stack.  A newline is printed after the value.

[F6] аргумент толкает 0 на dc стек инициализировать сумму.

9
ответ дан 23 May 2018 в 01:51
  • 1
    Что-то вроде этого может быть самым быстрым по большому набору данных – Digital Trauma 3 February 2017 в 06:26
  • 2
    @DigitalTrauma на 1,3 миллиона линий, на самом деле почти самый медленный: real 0m4.234s – Jacob Vlijm 3 February 2017 в 10:14
  • 3
    забава - это все, что нужно для взлома: D слишком сложный: D: D – Rinzwind 3 February 2017 в 12:37
  • 4
    Пожалуйста, объясните это немного. – AmanicA 7 February 2017 в 07:25

В Bash:

#! /bin/bash

file="YOUR_FILE.txt"

TOTAL=0
while IFS= read -r line
do
    TOTAL=$(( TOTAL + line ))
    echo $TOTAL
done <"$file"
8
ответ дан 23 May 2018 в 01:51
  • 1
    bash чрезвычайно медленный на этом: real 0m53.116s, почти минута, на 1,3 миллиона строк :) – Jacob Vlijm 3 February 2017 в 10:22
  • 2
    @JacobVlijm тире примерно в два раза быстрее, busybox ash и zsh (в режиме sh) 1,5 раза, но, конечно, даже тире в 5 раз медленнее, чем python. – muru 3 February 2017 в 13:04

Чтобы напечатать частичные суммы целых чисел, заданные на стандартном входе один на строку:

#!/usr/bin/env python3
import sys

partial_sum = 0
for n in map(int, sys.stdin):
    partial_sum += n
    print(partial_sum)

Пример запуска.

Если по какой-то причине команда слишком медленная; вы можете использовать программу C:

#include <stdint.h>
#include <ctype.h>
#include <stdio.h>

int main(void)
{
  uintmax_t cumsum = 0, n = 0;
  for (int c = EOF; (c = getchar()) != EOF; ) {
    if (isdigit(c))
      n = n * 10 + (c - '0');
    else if (n) { // complete number
      cumsum += n;
      printf("%ju\n", cumsum);
      n = 0;
    }
  }
  if (n)
    printf("%ju\n", cumsum + n);
  return feof(stdin) ? 0 : 1;
}

Чтобы создать и запустить, введите:

$ cc cumsum.c -o cumsum
$ ./cumsum < input > output

Пример запуска .

UINTMAX_MAX is 18446744073709551615.

Код C в несколько раз быстрее, чем команда awk на моей машине для входного файла, сгенерированного с помощью:

#!/usr/bin/env python3
import numpy.random
print(*numpy.random.random_integers(100, size=2000000), sep='\n')
6
ответ дан 23 May 2018 в 01:51

Вероятно, вы хотите что-то вроде этого:

sort -n <filename> | uniq -c | awk 'BEGIN{print "Number\tFrequency"}{print $2"\t"$1}'

Объяснение команды:

sort -n <filename> | uniq -c сортирует вход и возвращает частотную таблицу | awk 'BEGIN{print "Number\tFrequency"}{print $2"\t"$1}', превращает вывод в более удобный Формат

Пример: Входной файл list.txt:

4
5
3
4
4
2
3
4
5

Команда:

$ sort -n list.txt | uniq -c | awk 'BEGIN{print "Number\tFrequency"}{print $2"\t"$1}'
Number  Frequency
2   1
3   2
4   4
5   2
5
ответ дан 23 May 2018 в 01:51

Вы можете сделать это в vim. Откройте файл и введите следующие нажатия клавиш:

qaqqayiwj@"<C-a>@aq@a:wq<cr>

Обратите внимание, что <C-a> на самом деле ctrl-a, а <cr> - возврат каретки, то есть кнопка ввода.

Вот как это работает. Во-первых, мы хотим очистить регистр «а», чтобы он не имел побочных эффектов в первый раз. Это просто qaq. Затем мы делаем следующее:

qa                  " Start recording keystrokes into register 'a'
  yiw               " Yank this current number
     j              " Move down one line. This will break the loop on the last line
      @"            " Run the number we yanked as if it was typed, and then
        <C-a>       " increment the number under the cursor *n* times
             @a     " Call macro 'a'. While recording this will do nothing
               q    " Stop recording
                @a  " Call macro 'a', which will call itself creating a loop

После выполнения этого рекурсивного макроса мы просто вызываем :wq<cr> для сохранения и выхода.

5
ответ дан 23 May 2018 в 01:51
  • 1
    +1 для разрушения магического заклинания и объяснения всех частей. Слишком редко вокруг этих частей. – John U 3 February 2017 в 19:00

Perl one-liner:

$ perl -lne 'print $sum+=$_' input.txt                                                                
3
7
12
20

С 2,5 миллионами строк чисел требуется обработать 6,6 секунды:

$ time perl -lne 'print $sum+=$_' large_input.txt > output.txt                                        
    0m06.64s real     0m05.42s user     0m00.09s system

$ wc -l large_input.txt
2500000 large_input.txt
5
ответ дан 23 May 2018 в 01:51
  • 1
    real 0m0.908s, довольно приятно. – Jacob Vlijm 3 February 2017 в 01:36
  • 2
    @JacobVlijm, который находится в довольно маленьком файле. Я добавил небольшой тест с 2,5 млн. Строк файла. 6,64 секунды – Sergiy Kolodyazhnyy 3 February 2017 в 01:46
  • 3
    Я потратил 1,3 миллиона строк на древнюю систему – Jacob Vlijm 3 February 2017 в 01:47

Простой однострочный Bash:

x=0 ; while read n ; do x=$((x+n)) ; echo $x ; done < INPUT_FILE

x - суммарная сумма всех чисел из текущей строки и выше. n - это число в текущей строке.

Мы перебираем все строки n из INPUT_FILE и добавляем их числовое значение к нашей переменной x и печатаем эту сумму во время каждой итерации.

Bash здесь немного медленнее, вы можете ожидать, что это заработает около 20-30 секунд для файла с 2 миллионами записей, без печати вывода на консоль (что еще медленнее, независимо от способ вы используете).

3
ответ дан 23 May 2018 в 01:51

Как и при ответе @ steeldriver, но с немного менее загадочным bc вместо этого:

sed 's/.*/a+=&;a/' input | bc

Самое приятное в bc (и dc) заключается в том, что они являются произвольными калькуляторами точности , поэтому никогда не будет переполняться или испытывать недостаток точности над целыми числами.

Выражение sed преобразует вход в:

a+=3;a
a+=4;a
a+=5;a
a+=8;a

. Затем это оценивается с помощью bc. Параметр a bc автоматически инициализируется до 0. Каждая строка увеличивает a, затем явно печатает его.

3
ответ дан 23 May 2018 в 01:51
  • 1
    real 0m5.642s на 1,3 миллиона линий. sed действительно медленный на этом. – Jacob Vlijm 3 February 2017 в 10:17

Другие вопросы по тегам:

Похожие вопросы: