免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
123下一页
最近访问板块 发新帖
查看: 9763 | 回复: 24
打印 上一主题 下一主题

求助:perl hash中多元键和值的问题 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2012-12-09 13:57 |只看该作者 |倒序浏览
一个文件,有n行9列,第一列有13个不同的元素,第七列是正反向。第四列和第五列是起始和终止的位置,其余列不用管。
简化成一个这样的文件:

name     direction     start      end
a1           +               1           3
a1           +               4           5
a1           -                2           4
a1           -                5           6
a2           +               3           7
a2           -                1           5

想得到的结果是:
a1    +    1     3     4      5
a1    -     2     4     5      6
a2    +    3     7
a2    -     1      5

我的思路是,将前两列作为hash的键,后两列作为hash的值来进行处理。但while (<IN>),它是一行一行处理,到最后打印时,只打印出循环的最后一行结果。
拜托高手指点一下,谢谢了。。。

论坛徽章:
0
2 [报告]
发表于 2012-12-09 14:06 |只看该作者
目测是你把哈希定义在循环里面了~

论坛徽章:
0
3 [报告]
发表于 2012-12-09 14:17 |只看该作者
回复 2# kiwivip


    是,那是一个在服务器中的文件,我先得读进它。。。嗯,刚学perl不久,能指点一下么?谢谢了~

论坛徽章:
0
4 [报告]
发表于 2012-12-09 14:43 |只看该作者
回复 3# 小猪Gina
  1. %hash=();
  2. while(<IN>) {
  3.     ($name,$direction,$start,$end)=(split)[0,6,3,4];
  4.     if (defined($hash{$name}{$direction})) {
  5.         my @tmp=(@{$hash{$name}{$direction}},$start,$end);
  6.         $hash{$name}{$direction}=\@tmp;
  7.     } else {
  8.         $hash{$name}{$direction}=[$start,$end];
  9.     }
  10. }
  11. foreach $n (sort keys %hash) {
  12.     foreach $d (sort keys %{$hash{$n}} ) {
  13.       print "$n $d @{$hash{$name}{$direction}}\n";
  14. }
复制代码

论坛徽章:
0
5 [报告]
发表于 2012-12-09 17:17 |只看该作者
回复 4# cecial


    谢谢您,可以问一下 (split)[0,6,3,4];的含义吗?谢谢~

论坛徽章:
0
6 [报告]
发表于 2012-12-09 18:20 |只看该作者
先谢谢三楼的帮助,不过那个(split)[0,6,3,4];确实不明白,在他给的代码的基础上,稍微更改整理了一下,下面的代码运行过了,是可以正确运行的。
my %hash=();
while(<IN>) {
        my($name,$direction,$start,$end)=split(/\s+/,$_);
        if (defined($hash{$name}{$direction})) {
                my @tmp=(@{$hash{$name}{$direction}},$start,$end);
        $hash{$name}{$direction}=\@tmp;
        }else{
                $hash{$name}{$direction}=[$start,$end];
        }
}

foreach my $n (sort keys %hash) {
        foreach my $d (sort keys %{$hash{$n}} ) {
                print "$n $d @{$hash{$n}{$d}}\n";
        }
}

论坛徽章:
0
7 [报告]
发表于 2012-12-09 19:54 |只看该作者
现在又碰到了一个问题,那个文件的
name     direction     start      end
a1           +               4           5
a1           +               1           3

a1           -                2           4
a1           -                5           6
a2           +               3           7
a2           -                1           5

还是想得到
a1    +    1     3     4      5
a1    -     2     4     5      6
a2    +    3     7
a2    -     1      5

就是将 stat 列进行从小到大进行排序,可以指点一下么?谢谢~

论坛徽章:
0
8 [报告]
发表于 2012-12-09 22:37 |只看该作者
问题已解决了。代码分享给那些需要的人吧~
open (IN,"< test.txt") || die "Can't open \n";
my %hash=();
my @arrays = <IN>;
my @lie = sort {(split /\s+/,$a)[2] <=> (split /\s+/,$b)[2] }@arrays;

for (my $i=0;$i<=$#lie;$i++) {
        my @line=split(/\s+/,$lie[$i]);
        my($name,$direction,$start,$end)=("$line[0]","$line[1]","$line[2]","$line[3]");
        if (defined($hash{$name}{$direction})) {
        my @tmp=(@{$hash{$name}{$direction}},$start,$end);
        $hash{$name}{$direction}=\@tmp;
        }else{
                $hash{$name}{$direction}=[$start,$end];
        }   
}

foreach my $n (sort keys %hash) {
        foreach my $d (sort keys %{$hash{$n}} ) {
                print "$n $d @{$hash{$n}{$d}}\n";
        }
}
close (IN);

经过试验,没有问题的。

论坛徽章:
0
9 [报告]
发表于 2012-12-09 23:12 |只看该作者
回复 8# 小猪Gina


    排序完全可以放在输出啊,省去了第一次的split+排序。
我优化了一下:
  1. #!/usr/bin/perl
  2. use strict;
  3. use warnings;
  4. use Data::Dumper;

  5. my $title = <DATA>;
  6. my %hash = ();
  7. while (<DATA>) {
  8.     my ($name,$direction,$start,$end) = split;
  9.     push @{ $hash{"$name\t$direction"}}, $start, $end;
  10. }
  11. foreach my $k ( sort keys %hash ) {
  12.     print join("\t", $k, sort { $a <=> $b } @{$hash{$k}}), "\n",
  13. }
  14. __DATA__
  15. name     direction     start      end
  16. a1           +               4           5
  17. a1           +               1           3
  18. a1           -                2           4
  19. a1           -                5           6
  20. a2           +               3           7
  21. a2           -                1           5
复制代码

论坛徽章:
3
CU十二周年纪念徽章
日期:2013-10-24 15:41:34子鼠
日期:2013-12-14 14:57:19射手座
日期:2014-04-25 21:23:23
10 [报告]
发表于 2012-12-10 11:05 |只看该作者
  1. #!/usr/bin/perl
  2. use strict;
  3. use warnings;
  4. use Data::Dumper;
  5. my %hash;
  6. my $title;
  7. while(<DATA>){
  8.     if(/(\w+\s+(?:\+|-))\s+(\d+)\s+(\d+)/){
  9.         push @{$hash{$1}},$2,$3;
  10.     }else{
  11.         $title = $_;
  12.     }
  13. }
  14. map{print "$_\t";print join("\t",sort{$a cmp $b}@{$hash{$_}});print "\n"}sort keys %hash;

  15. __DATA__
  16. name     direction     start      end
  17. a1           +               4           5
  18. a1           +               1           3
  19. a1           -                2           4
  20. a1           -                5           6
  21. a2           +               3           7
  22. a2           -                1           5
复制代码
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP