对参与两个参数的哈希进行排序

时间:2016-11-10 12:33:39

标签: perl sorting perl-module

我使用以下格式的密钥哈希:

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;
}

有什么建议吗?

2 个答案:

答案 0 :(得分:6)

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

答案 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