我有一个文本文件,大约有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命令的解决方案。
编辑:添加了我如何读取文件。
答案 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几乎使结果减半。