24小时热门版块排行榜    

CyRhmU.jpeg
南方科技大学公共卫生及应急管理学院2025级博士研究生招生报考通知
查看: 914  |  回复: 4

淡蓝幽香

新虫 (初入文坛)

[交流] perl程序继续中,脸红贴上自写程序,求拍砖。已有2人参与

首先,大力感谢cdtits 同学在另外一个帖子提供的帮助,下面的程序有涉及部分。

本人有如下两个文件:
Doc1
1        NA1        0        0        1
1        NA2        0        0        2
1        295        NA1        NA2        2
1        NA5        0        0        1
1        4        NA5        295        1
1        36        NA6        100        2
1        NA6        0        0        1
1        155        NA6        100        2
1        NA7        4        36        2
2        NA8        0        0        1
2        NA10        0        0        1
2        NA11        0        0        2
2        99        NA8        NA9        2
2        8        NA10        NA11        1
2        390        8        99        1
3        NA12        0        0        1
3        NA13        0        0        2
3        753        NA12        NA13        2
3        NA14        0        0        1
3        9        NA14        753        1
3        NA15        0        0        1
3        NA16        0        0        2
3        186        NA14        753        2
3        722        NA15        NA16        1
3        397        722        186        1
3        396        722        186        1

Doc2
295        2908        2        0      

186        2612        3        1      

722        2827        1        0      

753        8601        3        na      

100        1881        na        na      

4        6358        2        0      

155        4627        2        0      

99        2996        2        0      

1.两个文件的关系:
Doc2中的每一行的第一列数字项,都分别对应Doc1每一行的第二,第三,或者第四列纯数字项。

2.文件特点描述:
所有文件的列之间,都用制表符分隔
Doc1,每一行的第一列都是数字;第二,三,四列可能是数字,也可能是NAi(i代表数字)的组合;第五列是数字或者na。
Doc2,每一行的第一列均为纯数字,最多不超过三位数;第二列也是纯数字,都是固定的四位数;第三列和第四列要么是个位数字,要么就是na。
3.目的:
        在Doc1的每一行第二,三,四列的纯数字项中,分别找到他们各自在Doc2对应数据。用Doc2的第二列数据去取代在Doc1 中的原始数据。要把Doc2 中得最后两项补到Doc1后面。其中这部分的补充决定权在与Doc1的第二列(见另部分例子)。
如:        doc1的第三行:1        295        NA1        NA2        2
         在doc2中对应的行是295        2908        2        0
          结果是:        1        2908        NA1        NA2        2        2(此处用4个制表符分隔)0
另:        doc1        1        4        NA5        295        1;doc2         4        6358        2        0
结果是:        1        6358        NA5        2908        1        2        0

很惭愧地贴上我写的程序,求帮助,求批评,求指正:另外,怎样修改程序,才能让它跑起来更快呢?
use strict;
use warnings;

my $outfile = "o.txt";
open (OUT, ">$outfile"or die("cannot open file";

my $A   = "A.txt";
open(IN, "<$a";

my $C   = "C.txt";
open(C, "<$C";
      
my %code;
my $num = 0;

while (my $l =
{      
                $l =~ s/^\s+//g;
            $l =~ s/\s+$//g;
            next if !length($l);                                               
            my($key, $value) = split (/\t/,$l,2);
            $code{$key} = $value;
}      

close C;
      
my $value;
while (my $line =
{
            $line  =~ s/^\s+//g;
            $line  =~ s/\s+$//g;
            next if !length($line);                                               
             $line =~ /^\d+\t(\w+\d+|\d+)\t(\w+\d+|\d+)\t(\w+\d+|\d+)\t.+/g;
             my ($m1,$m2,$m3)=($1,$2,$3);
           
            for my $key (keys %code)
            {         
                    if ($m1 =~ /^\d+$/ && $key == $m1 )               
                    {
                            my ($v1,$v2) = split(/\t/,$code{$key},2);
                            $line =~ s/$m1/$v1/;
                            my ($d1,$d2) = (/\t/,$v2,2);
                            print OUT "$line\t$d1\t\t\t\t$d2\n";
                    }
                    elsif($m2 =~ /^\d+$/ && $key == $m2)                                    
{
                            my ($v1,$v2) = split(/\t/,$code{$key},2);
                            $line =~ s/$m2/$v1/;
                            print OUT $line."\n";
                    }                     
                    elsif($m3 =~ /^\d+$/ && $key == $m3)                                    
{
                            my ($v1,$v2) = split(/\t/,$code{$key},2);
                            $line =~ s/$m3/$v1/;
                            print OUT $line."\n";
                    }
#头大,写不下去了。。。。错误好多。。。。
           }
}      
        close IN;
close OUT;
回复此楼
已阅   回复此楼   关注TA 给TA发消息 送TA红花 TA的回帖

anntoy

木虫 (著名写手)

★ ★
小木虫: 金币+0.5, 给个红包,谢谢回帖
xzhdty: 金币+1, 谢谢参与 2012-07-10 15:41:59
代码应该写在代码块里
也就是
CODE:
[code]、

[/code]之间
2楼2012-07-10 08:38:14
已阅   回复此楼   关注TA 给TA发消息 送TA红花 TA的回帖

jackie1179

木虫 (正式写手)

★ ★ ★
小木虫: 金币+0.5, 给个红包,谢谢回帖
xzhdty: 金币+2, 谢谢参与 2012-07-10 15:42:21
给你写了个,希望能帮到你,另外你有一点说的不是很清楚,如果Doc1的第二列在Doc2中未匹配,而其他列有匹配,要在其后补充吗?本代码不进行补充。
CODE:
#!/usr/bin/perl -w

unless (@ARGV) {
  die "Arguments not enough!";
}

$doc1 = $ARGV[0];
$doc2 = $ARGV[1];
undef %string;
open(DOC2,"$doc2") || die "Cannot open this file!$!";
while() {
  next if(/^\n/);
  chomp;
  
  @array = split /\t/;
  $string{$array[0],2} = $array[1];
  $string{$array[1],3} = $array[2];
  $string{$array[1],4} = $array[3];
}
close DOC2;


open(DOC1,"$doc1") || die "Cannot open this file!$!";
$out = "output";
open(OUT,">$out") || die "Cannot write to this file!$!";
while() {

  chomp;
  @array = split /\t/;
  print $array[2],"=>",&isPureDigit($array[2]),"\n";
  $mark = 0;
  foreach $i(1 .. 3) {
    if(&isPureDigit($array[$i]) && defined $string{$array[$i],2}) {
      if($i == 1) { $mark = 1; }
      $array[$i] = $string{$array[$i],2};
    }
  }
  foreach (@array) {
    print OUT "$_\t";
  }
  if($mark == 1) {
    print OUT "$string{$array[1],3}\t\t\t\t$string{$array[1],4}";
  }
  print OUT "\n";

}

close DOC1;
close OUT;

sub isPureDigit {
  $arg = shift;
  if($arg =~ /^NA/) {
    return 0;
  } else {
    return 1;
  }  
}

3楼2012-07-10 10:42:40
已阅   回复此楼   关注TA 给TA发消息 送TA红花 TA的回帖

jackie1179

木虫 (正式写手)


小木虫: 金币+0.5, 给个红包,谢谢回帖
不好意思,忘了说用法:
保存为文件pro.pl
perl  ./pro.pl  doc1 doc2
输出文件名为 output
4楼2012-07-10 10:44:45
已阅   回复此楼   关注TA 给TA发消息 送TA红花 TA的回帖

淡蓝幽香

新虫 (初入文坛)

引用回帖:
3楼: Originally posted by jackie1179 at 2012-07-10 10:42:40
给你写了个,希望能帮到你,另外你有一点说的不是很清楚,如果Doc1的第二列在Doc2中未匹配,而其他列有匹配,要在其后补充吗?本代码不进行补充。

#!/usr/bin/perl -w

unless (@ARGV) {
  die "Argumen ...

非常感谢哦。

关于你提到的:Doc1的第二列在Doc2中未匹配,而其他列有匹配,要在其后补充吗?

这个不用补充,只有Doc1第一列,在找到Doc2中的匹配项后, 需要补充。Doc1的其他列都不用
5楼2012-07-10 19:49:53
已阅   回复此楼   关注TA 给TA发消息 送TA红花 TA的回帖
相关版块跳转 我要订阅楼主 淡蓝幽香 的主题更新
普通表情 高级回复(可上传附件)
信息提示
请填处理意见