Perl;如何按值筛选哈希(指定条件)
我对perl语言不是很精通,但我遇到了一个我无法解决的问题,即使在网上做了很长时间的研究。 简单地说,我有这样一个散列:Perl;如何按值筛选哈希(指定条件),perl,hash,filter,subset,Perl,Hash,Filter,Subset,我对perl语言不是很精通,但我遇到了一个我无法解决的问题,即使在网上做了很长时间的研究。 简单地说,我有这样一个散列: my %HoH = ( chr1 => { start => 30, end => 55, }, chr1 => { start => 18, end => 21, }, chr1 => { start => 30, end => 80, } ); 我只是想找到一种方法来过滤它(我的意思是,在输出
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, }
);
作为第一次尝试,我想尝试以下内容:
my %HoH = (
chr1 => { start => 30, end => 55, },
chr1 => { start => 18, end => 21, },
chr1 => { start => 30, end => 80, }
);
识别并删除带有“end”<40的所有元素,以及:
用“start”>60识别并删除所有元素
所以我试着:
grep { $HoH{$_}{"end"} < 40 } keys(%HoH);
delete $HoH{$_} for grep { $HoH{$_}{"end"} < 40} keys(%HoH);
打印出以下内容:
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";
}
这一次对我来说似乎很复杂,如果你们中有人能给我一些帮助,我会很高兴。使用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;
发生的情况是,它正在为chr1
获取最后一个唯一条目。散列键必须是唯一的正如另一张海报所提到的-你的问题不是你的散列合并,而是散列不能有重复的键:
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;
使用严格;
使用警告;
使用数据::转储程序;
我的%HoH=(
chr1=>{start=>30,end=>55,},
chr2=>{start=>18,end=>21,},
chr3=>{start=>30,end=>80,}
);
grep{$HoH{${“end”}<40}键(%HoH);
删除grep{$HoH{$}{“end”}<40}密钥(%HoH)的$HoH{$};
打印转储程序\%HoH;
这是正确的-注意不同的散列键。不过我要指出的是,您正在迭代密钥,将它们变灰,然后删除它们。最好是:
foreach my $element ( keys %HoH ) {
delete $HoH{$element}
unless ( $HoH{$element}{start} < 40
or $HoH{$element}{end} > 60 );
}
print Dumper \%HoH;
foreach my$元素(键%HoH){
删除$HoH{$element}
除非($HoH{$element}{start}<40
或$HoH{$element}{end}>60);
}
打印转储程序\%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;
使用严格;
使用警告;
使用数据::转储程序;
我的@AoH=(
{开始=>30,结束=>55,},
{开始=>18,结束=>21,},
{开始=>30,结束=>80,}
);
打印转储程序\@AoH;
my@filtered=grep{$\>{start}>40或$\>{end}<60}@AoH;
打印转储程序\@已过滤;
注意-在原始示例中,您的grep
/delete
行执行相同的操作,您可以执行复合grep
来测试这两种情况 你不可能有这样的数据结构,因为所有的键都是相同的,你是对的,我不记得散列的特性,它们不能在里面存储重复的键。最后一个解决方案似乎非常有用,而且操作很少!谢谢!!!!
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;