我在perl语言方面不是很专业但是我遇到了一个我无法解决的问题,即使经过长时间的网络研究。 简而言之,我有一个像这样的散列哈希:
my %HoH = (
chr1 => { start => 30, end => 55, },
chr1 => { start => 18, end => 21, },
chr1 => { start => 30, end => 80, }
);
我只想找到一种方法来过滤它(我的意思是,在输出中获得新的散列哈希)以获取特定值。特别是,给定一个区间,比方说40-60,我想要一个新的哈希散列,只有元素重叠这个区间。
换句话说,我想得到输出:
my %HoH = (
chr1 => { start => 30, end => 55, },
chr1 => { start => 30, end => 80, }
);
作为第一次尝试,我想尝试这样的事情:
使用"end" < 40
识别并删除所有元素,然后:
使用"start" > 60
识别并删除所有元素。
所以我试过了:
grep { $HoH{$_}{"end"} < 40 } keys(%HoH);
delete $HoH{$_} for grep { $HoH{$_}{"end"} < 40} keys(%HoH);
但是在两个过滤器中的第一个之后,我在输出中找到了最后一个元素,我真的不明白错误在哪里:
hash size is 1
chr1: start=30 end=80
打印出以下内容:
my $len = keys %HoH;
print "hash size is $len\n";
foreach my $chr ( keys %HoH ) {
print "$chr: ";
for my $position ( keys %{ $HoH{$chr} } ) {
print "$position=$HoH{$chr}{$position} ";
}
print "\n";
}
这次对我来说似乎相当复杂,如果有人能给我一些帮助,我会很高兴。
答案 0 :(得分:3)
使用Data::Dumper
检查您的哈希值,您会发现自己没有自己认为的数据结构:
use strict;
use warnings;
my %HoH = (
chr1 => {
start => 30,
end => 55,
},
chr1 => {
start => 18,
end => 21,
},
chr1 => {
start => 30,
end => 80,
},
);
print Dumper \%HoH;
$VAR1 = {
'chr1' => {
'start' => 30,
'end' => 80
}
};
正在发生的事情是它正在为chr1
获取最后一个唯一条目。哈希键必须是唯一的
答案 1 :(得分:3)
正如另一张海报所提到的 - 你的问题不是你的哈希合并,它的哈希不能有重复的键:
use strict;
use warnings;
use Data::Dumper;
my %HoH = (
chr1 => { start => 30, end => 55, },
chr2 => { start => 18, end => 21, },
chr3 => { start => 30, end => 80, }
);
grep { $HoH{$_}{"end"} < 40 } keys(%HoH);
delete $HoH{$_} for grep { $HoH{$_}{"end"} < 40} keys(%HoH);
print Dumper \%HoH;
这可以正常工作 - 注意不同的哈希键。我会注意到 - 你正在重复你的密钥,轻击它们,然后删除它们。可能更好:
foreach my $element ( keys %HoH ) {
delete $HoH{$element}
unless ( $HoH{$element}{start} < 40
or $HoH{$element}{end} > 60 );
}
print Dumper \%HoH;
你可以通过一系列哈希来做你想做的事情:
use strict;
use warnings;
use Data::Dumper;
my @AoH = (
{ start => 30, end => 55, },
{ start => 18, end => 21, },
{ start => 30, end => 80, }
);
print Dumper \@AoH;
my @filtered = grep { $_->{start} > 40 or $_->{end} < 60 } @AoH;
print Dumper \@filtered;
注意 - 在原始示例中,您的grep
/ delete
行正在执行相同操作,您可以执行复合grep
来测试这两个条件。