排序涉及两个参数的散列
Sort hash attending to two parameters
我有一个具有以下格式的密钥的散列:
scaffold_902_159
scaffold_2_1980420
scaffold_2_10
scaffold_10_402
我想打印出按以下格式排序的哈希值:
scaffold_2_10
scaffold_2_1980420
scaffold_10_402
scaffold_902_159
所以首先我必须按数字顺序处理第一个数字,然后再处理最后一个数字。我不想使用正则表达式搜索 "scaffold_",因为这可能会有所不同。我的意思是,我可以使用其他格式的散列,例如“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;
}
有什么建议吗?
Sort::Naturally 救援!
#!/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
这对两列进行排序,并使用 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 ? ( , ) : ( 0xffffffff, ) ) ]
} @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
)和数字排序 <=>
进行排序。该运算符 returns 0
如果 RHS 和 LHS 都相等,则 or ||
继续正确的表达式,然后按索引 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
我有一个具有以下格式的密钥的散列:
scaffold_902_159
scaffold_2_1980420
scaffold_2_10
scaffold_10_402
我想打印出按以下格式排序的哈希值:
scaffold_2_10
scaffold_2_1980420
scaffold_10_402
scaffold_902_159
所以首先我必须按数字顺序处理第一个数字,然后再处理最后一个数字。我不想使用正则表达式搜索 "scaffold_",因为这可能会有所不同。我的意思是,我可以使用其他格式的散列,例如“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;
}
有什么建议吗?
Sort::Naturally 救援!
#!/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
这对两列进行排序,并使用 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 ? ( , ) : ( 0xffffffff, ) ) ]
} @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
)和数字排序 <=>
进行排序。该运算符 returns 0
如果 RHS 和 LHS 都相等,则 or ||
继续正确的表达式,然后按索引 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