排序字符串和数字的哈希值

时间:2014-04-09 00:31:25

标签: perl sorting hashmap cisco

我有一个哈希键,例如:

FastEthernet1
GigabitEthernet1/1
GigabitEthernet1/10
GigabitEthernet1/2
GigabitEthernet1/20

但是我从1-48开始使用它们,我也有2/1 - 48等。

foreach my $i (sort keys %intconfigs)将完全按照上述方式打印。

但我想要的是:

FastEthernet1
GigabitEthernet1/1
GigabitEthernet1/2
GigabitEthernet1/10
GigabitEthernet1/20

我试过这个foreach my $i (sort { $a <=> $b } keys %intconfigs),但结果是:

GigabitEthernet1/2
GigabitEthernet1/10
GigabitEthernet1/20
GigabitEthernet1/1
FastEthernet1

不确定如何正确排序。任何帮助将不胜感激。

2 个答案:

答案 0 :(得分:2)

您可以将值分解为多个部分,以便您可以对每个部分进行适当的排序,无论是通过alpha还是通过数字比较:

my @keys = qw(
    FastEthernet1
    GigabitEthernet1/1
    GigabitEthernet1/10
    GigabitEthernet1/2
    GigabitEthernet1/20
);

my @sorted = sort {
    my ($a_name, $a_num1, $a_num2) = $a =~ m{(.*?)(\d+)(?:/(\d+))?};
    my ($b_name, $b_num1, $b_num2) = $b =~ m{(.*?)(\d+)(?:/(\d+))?};
    $a_name cmp $b_name or $a_num1 <=> $b_num1 or $a_num2 <=> $b_num2;
} @keys;

print "$_\n" for @sorted;

或使用一些更高级的正则表达式技术:

my @sorted = sort {
    local ( $a, $b ) = map { m{(?<name>\D+) (?<num1>\d+) (?: / (?<num2>\d+))?}x ? {%+} : die "Can't parse: $_" } ( $a, $b );
    $a->{name} cmp $b->{name} or $a->{num1} <=> $b->{num1} or $a->{num2} <=> $b->{num2}
} @keys;

或使用模块Sort::Key::Natural,以数字方式自动对数字部分进行排序:

use Sort::Key::Natural qw(natsort);

my @sorted = natsort @keys;

print "$_\n" for @sorted;

两种方法输出:

FastEthernet1
GigabitEthernet1/1
GigabitEthernet1/2
GigabitEthernet1/10
GigabitEthernet1/20

答案 1 :(得分:0)

在你的情况下可以使用的另一个简单的方法是对字符串的变体进行字符串排序,通过将所有嵌入的数字0填充到一长串数字中来形成,这样它们就能正确排序。

use List::UtilsBy qw( sort_by );

my @ifaces = sort_by { s/(\d+)/sprintf "%09d", $1/eg; $_ } qw(
  FastEthernet1
  GigabitEthernet1/1
  GigabitEthernet1/10
  GigabitEthernet1/2
  GigabitEthernet1/20
);

say for @ifaces

确实按照要求的顺序打印它们。

它不是一个通用的解决方案,因为在这种情况下,它会破坏包含长度超过9位的数字序列或浮点数的字符串。