如何在非常大的文本文件(~150 GB)中找到最大的数字?
How can I find the largest number in a very large text file (~150 GB)?
我有一个大约有 100000000 行的文本文件,每一行都属于以下类型:
string num1 num2 num3 ... num500
string num1 num2 num3 ... num40
我想找到此文件中存在的最大数字。
我当前的代码读取每一行,将其拆分为 space,并存储当前行中的最大数字。然后,我将它与下一行的最大数进行比较,并保留两者中较大的一个。
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 命令的解决方案。
编辑:添加了我阅读文件的方式。
这对于 awk 来说是一个微不足道的任务。
awk 'NR==1{m=} {for(i=2;i<=NF;++i) if(m<$i) m=$i} END{print m}' file
如果保证你的文件不全是零或负数,你可以去掉NR==1{m=}
部分。
试试这个 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
$
我想编写一个没有 for
循环列的 awk 脚本,以将执行时间与 for
循环解决方案(例如 @oguzismail 的 琐碎的 进行比较。我创建了 1-100 列数据的一百万条记录,值在 0-2^32 之间。我玩 RS
只比较第 2-100 列,但由于需要正则表达式,它减慢了执行速度。很多。使用 tr
交换 space 和换行符我非常接近:
$ cat <(echo 0) file | tr ' \n' '\n ' | awk 'max<{max=}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 几乎减半了结果。
我有一个大约有 100000000 行的文本文件,每一行都属于以下类型:
string num1 num2 num3 ... num500
string num1 num2 num3 ... num40
我想找到此文件中存在的最大数字。
我当前的代码读取每一行,将其拆分为 space,并存储当前行中的最大数字。然后,我将它与下一行的最大数进行比较,并保留两者中较大的一个。
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 命令的解决方案。
编辑:添加了我阅读文件的方式。
这对于 awk 来说是一个微不足道的任务。
awk 'NR==1{m=} {for(i=2;i<=NF;++i) if(m<$i) m=$i} END{print m}' file
如果保证你的文件不全是零或负数,你可以去掉NR==1{m=}
部分。
试试这个 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
$
我想编写一个没有 for
循环列的 awk 脚本,以将执行时间与 for
循环解决方案(例如 @oguzismail 的 琐碎的 进行比较。我创建了 1-100 列数据的一百万条记录,值在 0-2^32 之间。我玩 RS
只比较第 2-100 列,但由于需要正则表达式,它减慢了执行速度。很多。使用 tr
交换 space 和换行符我非常接近:
$ cat <(echo 0) file | tr ' \n' '\n ' | awk 'max<{max=}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 几乎减半了结果。