Как найти наибольшее число в очень большом текстовом файле (~ 150 ГБ)? - PullRequest
0 голосов
/ 01 января 2019

У меня есть текстовый файл, содержащий около 100000000 строк, каждый из которых имеет следующий тип:

string num1 num2 num3 ... num500
string num1 num2 num3 ... num40

Я хочу найти наибольшее число, присутствующее в этом файле.

Мой текущий кодчитает каждую строку, разделяет ее на пробелы и сохраняет наибольшее число в текущей строке.Затем я сравниваю его с наибольшим числом следующей строки и сохраняю большее из двух.

with open(filename,'r') as f:
    prev_max = -1
    for line in f:
        line = [int(n) for n in line.split(' ')[1:]]
        max = max_num(line)
        if max > prev_max:
            prev_max = max

Но это занимает вечность.Есть ли лучший способ сделать это?

Я открыт для решений с помощью awk или других команд оболочки.

Редактировать: Добавлено, как я читаю файл.

Ответы [ 3 ]

0 голосов
/ 01 января 2019

Попробуйте это решение Perl

$ cat sample1.txt
string 1 2 4 10 7
string 1 2 44 10 7
string 3 2 4 10 70
string 9 2 44 10 7
$ perl -lane ' $m=(sort {$b<=>$a} @F[1..$#F])[0]; $max=$m>$max?$m:$max ; END { print $max } ' sample1.txt
70
$
0 голосов
/ 01 января 2019

Я хотел написать сценарий awk без for зацикливания столбцов, чтобы сравнить время выполнения с for зацикленным решением, таким как тривиальное @ oguzismail.Я создал миллион записей из 1-100 столбцов данных, значения между 0-2 ^ 32.Я играл с RS, чтобы сравнивать только столбцы 2-100, но, поскольку это требовало регулярных выражений, это замедляло выполнение.Многое.Используя tr для обмена пробелами и символами новой строки, я довольно близко подошел:

$ cat <(echo 0) file | tr ' \n' '\n ' | awk 'max<$1{max=$1}END{print max}'

Вывод cat <(echo 0) file | tr ' \n' '\n ':

0 string1
1250117816
3632742839
172403688 string2
2746184479
...

Использовано тривиальное решение :

real    0m24.239s
user    0m23.992s
sys     0m0.236s

тогда как мой tr + awk потратил:

real    0m28.798s
user    0m29.908s
sys     0m2.256s

(удивительно, если я сначала предварительно обработал данные с помощью tr в файл, а затем прочитал их с помощью awk itне будет быстрее, в большинстве случаев на самом деле медленнее)

Итак, я решил проверить свои ржавые навыки C, чтобы установить какой-то базовый уровень (справочные страницы довольно хороши. И Google.):

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(void)
{
  FILE * fp;
  char * line = NULL;
  char * word = NULL;
  size_t len = 0;
  ssize_t read;
  long max=0;
  long tmp=0;

  fp = fopen("file", "r");
  if (fp == NULL)
    exit(EXIT_FAILURE);
  while ((read = getline(&line, &len, fp)) != -1) {
    if((word = strtok(line," "))!=NULL) {
      while(word != NULL) {
        if((word = strtok(NULL," "))!=NULL) {
          tmp=strtol(word,NULL,10);
          if(max<tmp) {
            max=tmp;
          }
        }
      }
    }
  }
  fclose(fp);
  printf("%ld\n",max);
  exit(EXIT_SUCCESS);
}

Результат этого:

$ time ./a.out 
4294967292

real    0m9.307s
user    0m9.144s
sys     0m0.164s

О, использование mawk вместо gawk почти вдвое уменьшило результаты.

0 голосов
/ 01 января 2019

Это тривиальное задание для awk.

awk 'NR==1{m=$2} {for(i=2;i<=NF;++i) if(m<$i) m=$i} END{print m}' file

Если гарантировано, что в вашем файле не все нули или отрицательные числа, вы можете удалить NR==1{m=$2} part.

...