如何在非常大的文本文件(〜150 GB)中找到最大的数字?

时间:2019-01-01 05:20:13

标签: python-3.x text awk large-data

我有一个文本文件,大约有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或其他shell命令的解决方案。

编辑:添加了我如何读取文件。

3 个答案:

答案 0 :(得分:4)

对于awk来说这是一项微不足道的任务。

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

如果可以确保文件不全为零或负数,则可以删除m==""{ m=$2 }部分。

答案 1 :(得分:1)

尝试此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
$

答案 2 :(得分:0)

我想编写一个awk脚本,而不用for循环列以将执行时间与for循环解决方案(例如@oguzismail的琐事)进行比较。我创建了100万列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读取它,它的速度不会更快,实际上大多数时候会更慢)

因此,然后我决定测试我生锈的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几乎使结果减半。