免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: kidaaaa
打印 上一主题 下一主题

关于从两个文件中提取需要的行,大家帮我看看为啥我的脚本执行效率超低 [复制链接]

论坛徽章:
0
11 [报告]
发表于 2010-05-22 12:10 |只看该作者
回复 9# iamlimeng
  1.     #!/usr/bin/perl

  2. use strict;
  3. use warnings;
  4. my %hash;
  5. open PTT, "file1" or die 'Can not open the required file file1 !';
  6. while (my $PTT_line = <PTT>)
  7. {
  8.     my @ptt = split /\s+/, $PTT_line;
  9.     push @{$hash{$ptt[0]},[@ptt];
  10. }
  11. close PTT;

  12. open BR, "file2" or die 'Can not open the required file file2 !';
  13. while (my $BR_line = <BR>) {
  14.     my @br = split /\s+/, $BR_line;
  15.     if(exists $hash{$br[0]})
  16.     {
  17.        foreach my $item (@{$hasn{$br[0]}})
  18.        {
  19.             if(($br[8] >= $item->[1]) and ($br[9] <= $item->[2]))
  20.             {
  21.                 chomp $BR_line;
  22.                 print $BR_line , '    ', join "\t",@$item;
  23.             }
  24.         }
  25.     }
  26. }
  27. close BR;
复制代码
是可行的 只是多用点内存而已

论坛徽章:
0
12 [报告]
发表于 2010-05-22 12:31 |只看该作者
本帖最后由 iamlimeng 于 2010-05-22 12:43 编辑

回复 11# hu145165

学习了,在内存够大的情况确实是很好很高效的方法,这是关系型数据库的方法,我想到要用HASH过滤数据,减少计算,但没找到这个方法。

如果想节省内存,可以考虑在%hash中只存储@PTT的索引(行号),在条件判断时再去SPLIT,那样内存中就只有file1的数组@PTT和一个数据量不太大的%hash.
  1. #!/usr/bin/perl

  2. use strict;
  3. use warnings;

  4. my %hash;
  5. open PTT, "file1" or die 'Can not open the required file file1 !';
  6. my @PTT = <PTT>;
  7. close PTT;

  8. for (0..$#PTT)
  9. {
  10.     my @ptt = split /\s+/, $PTT[$_];
  11.     push @{$hash{$ptt[0]}},$_;
  12. }

  13. open BR, "file2" or die 'Can not open the required file file2 !';
  14. while (my $BR_line = <BR>) {
  15.     my @br = split /\s+/, $BR_line;
  16.     if(exists $hash{$br[0]})
  17.     {
  18.        foreach my $no (@{$hash{$br[0]}})
  19.        {
  20.                my @ptt = split /\s+/, $PTT[$no];
  21.             if($br[8] >= $ptt[1] and $br[9] <= $ptt[2])
  22.             {
  23.                 chomp $BR_line;
  24.                 print $BR_line , '    ', join ' ',$PTT[$no];
  25.             }
  26.         }
  27.     }
  28. }
  29. close BR;
复制代码

论坛徽章:
0
13 [报告]
发表于 2010-05-22 13:01 |只看该作者
另外,在我的印象中,处理同样大小的数据,HASH的内存开销大于数组,且效率也低于数组。那在处理大量数据的情况下,效率应该区别明显。

所以请楼主把各种方法都运行一次,并记录运行时间,并贴出来。这样也好让大家对HASH和数组在处理同样大小的大量数据时的效率有个了解。

论坛徽章:
0
14 [报告]
发表于 2010-05-22 13:16 |只看该作者
太感谢楼上各位的帮助了,我这就试试

论坛徽章:
0
15 [报告]
发表于 2010-05-22 13:45 |只看该作者
另外,解释一下,我说的是“当:文件1的第一列等于文件2的第二列”
这是一个条件判断,不是文件本有的性质。

论坛徽章:
0
16 [报告]
发表于 2010-05-22 20:33 |只看该作者
本帖最后由 kidaaaa 于 2010-05-22 20:35 编辑

呃。。。。。。各位的代码都是基于假设我的文件1的第一列是唯一的。可是遗憾的告诉大家,不是这样。
文件1的第一列是有重复的。

我这两个文件中只有文件2的第一列是唯一的,但是这一列数据却并不参与我的筛选条件当中。除此之外,其它数据列都没有唯一性。
杯具啊!!

像我这样的数据提取任务是不是交给数据库程序来完成更好啊?希望大家指点下,我初步尝试过用mysql来处理,貌似并不快。不知是我查询优化不好还是mysql的大数据量处理能力不好的原因?

论坛徽章:
0
17 [报告]
发表于 2010-05-22 21:23 |只看该作者
自己使用
Benchmark
查看瓶颈在那

初步 观察  
my @br = split /\s+/, $BR_line;
这种写法 很可能是原因所在
不要直接丢到一个数组里面去

改成
my ($c1,undef, $c3,undef,...) = split /\s+/, $BR_line;
这种形式

如果效率还是达不到  就换C吧  
这种简单功能来说 自己通过优化实现应该会比使用数据库效率高

论坛徽章:
0
18 [报告]
发表于 2010-05-22 21:25 |只看该作者
在while里面
去掉你所有的  数组 操作  
直接使用标量  效率肯定会提高的

论坛徽章:
0
19 [报告]
发表于 2010-05-23 00:00 |只看该作者
先按要比较的那两列给文件排下序,是不是能省掉很多运算。

论坛徽章:
0
20 [报告]
发表于 2010-05-23 00:31 |只看该作者
对本帖的几种算法进行了简单的效率分析,见:

http://bbs3.chinaunix.net/thread-1708793-1-1.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP