我使用以下格式的密钥哈希:
scaffold_902_159
scaffold_2_1980420
scaffold_2_10
scaffold_10_402
我想打印出以下列格式排序的哈希:
scaffold_2_10
scaffold_2_1980420
scaffold_10_402
scaffold_902_159
首先,我必须以数字方式订购第一个号码,然后参加最后一个号码。我不想要一个正则表达式来搜索"脚手架_"因为这可能会有所不同我的意思是,我可以使用其他格式的哈希,例如" blablabla_NUMBER_NUMBER ,或 blablablaNUMBER_NUMBER "。键 _NUMBER 的最后一部分是永久性的。
我已经使用了这段代码,但只对数字进行排序:
my @keys = sort {
my ($aa) = $a =~ /(\d+)/;
my ($bb) = $b =~ /(\d+)/;
$aa <=> $bb;
} keys %hash;
foreach my $key (@keys) {
print $key;
}
有什么建议吗?
答案 0 :(得分:6)
#!/usr/bin/perl
use strict;
use warnings;
use Sort::Naturally qw(nsort);
my %hash = (
scaffold_902_159 => 'v1',
scaffold_2_1980420 => 'v2',
scaffold_2_10 => 'v3',
scaffold_10_402 => 'v4',
);
print "$_\n" for nsort keys %hash;
输出:
scaffold_2_10
scaffold_2_1980420
scaffold_10_402
scaffold_902_159
根据您的查询,尝试了一些中间没有数字的键。
#!/usr/bin/perl
use strict;
use warnings;
use Sort::Naturally qw(nsort);
my @keys = qw(
should_come_last_9999_0
blablabla_10_403
scaffold_902_159
scaffold_2_1980420
scaffold_2_10
scaffold_10_402
blablabla902_1
blablabla901_3
);
print "$_\n" for nsort @keys;
输出:
blablabla_10_403
blablabla901_3
blablabla902_1
scaffold_2_10
scaffold_2_1980420
scaffold_10_402
scaffold_902_159
should_come_last_9999_0
答案 1 :(得分:3)
对两列进行排序,并使用Schwartzian transform从字符串中创建这些列。
use strict;
use warnings;
use feature 'say';
my @keys = qw(
scaffold_902_159
scaffold_2_1980420
scaffold_2_10
scaffold_10_402
);
@keys =
map { $_->[0] } # transform back
sort { $a->[1] <=> $b->[1] || $a->[2] <=> $b->[2] } # sort
map { # transform
m/(\d+)(?:\D+(\d+))/;
[ $_, ( defined $2 ? ( $1, $2 ) : ( 0xffffffff, $1 ) ) ]
} @keys;
say for @keys;
输出:
scaffold_2_10
scaffold_2_1980420
scaffold_10_402
scaffold_902_159
初始转换map
返回的数据结构如下所示:
[ 'scaffold_902_159', 902, 159 ]
sort
使用它来首先按索引1(902
)排序,并使用数字排序<=>
。如果RHS和LHS都相等,则该运算符返回0
,因此或||
继续使用正确的表达式,然后对索引2(159
)进行排序。
因为您说第一个数字是可选的,如果只有第二个数字应该是最后一个,我们必须用非常高的数字代替。不进入64位整数,0xffffffff
是我们可以做的最高数字。
第二个map
从数组引用的索引0
中提取完整键。
如果我们在输入中添加其他内容,例如您建议的blablablaNUMBER_NUMBER
,它仍然只会对数字上的进行排序,并完全忽略字符串部分。
my @keys = qw(
should_come_last_9999_0
blablabla_10_403
scaffold_902_159
scaffold_2_1980420
scaffold_2_10
scaffold_10_402
no_first_number_1
);
这是输出:
scaffold_2_10
scaffold_2_1980420
scaffold_10_402
blablabla_10_403
blablabla902_1
scaffold_902_159
should_come_last_9999_0
no_first_number_1