对具有字母数字值的哈希数组进行排序

时间:2014-06-13 06:42:00

标签: arrays regex perl sorting perl-data-structures

我面临着排序哈希数组的问题;哈希具有我需要排序的字母数字值。

请参阅此question!我的问题是这个问题的延伸。 我在上面的问题中尝试了解决方案,但没有得到所需的输出。

$arr_ref = [
  { brand => "A.1", PO => "1.a", supplier => "X" },
  { brand => "A.2", PO => "2.a", supplier => "X" },
  { brand => "B.1", PO => "1.b", supplier => "X" },
  { brand => "B.2", PO => "2.b", supplier => "X" },
  { brand => "B.3", PO => "1.c", supplier => "Y" },
]

我需要按品牌或PO排序。

#sort the array reference and place the array back into the standard_set
$arr_ref = [sort by_brand @$arr_ref];
sub by_brand {
    $a->{brand} cmp $b->{brand}
}

复杂性是关键;可以从数字或字母字符开始。 品牌或PO也可以具有不同的尺寸。分隔符可以是点或超级。

我们可以根据$arr_ref收到的输入来解决这个问题吗?

4 个答案:

答案 0 :(得分:1)

你真的很亲密。您只需删除[]括号,然后取消引用要分配给@$array_ref = ...的数组。

use strict;
use warnings;

my $arr_ref = [
  { brand => "B.3", PO => "1.c", supplier => "Y" },
  { brand => "B.2", PO => "2.b", supplier => "X" },
  { brand => "B.1", PO => "1.b", supplier => "X" },
  { brand => "A.2", PO => "2.a", supplier => "X" },
  { brand => "A.1", PO => "1.a", supplier => "X" },
];

my @sorted = sort { $a->{brand} cmp $b->{brand} } @$arr_ref;

use Data::Dump;
dd @sorted;

输出:

(
  { brand => "A.1", PO => "1.a", supplier => "X" },
  { brand => "A.2", PO => "2.a", supplier => "X" },
  { brand => "B.1", PO => "1.b", supplier => "X" },
  { brand => "B.2", PO => "2.b", supplier => "X" },
  { brand => "B.3", PO => "1.c", supplier => "Y" },
)

答案 1 :(得分:1)

使用Schwartzian transform对其进行排序,并为每个字段更正比较器。

use strict;
use warnings;
use Data::Dumper;
my $arr_ref = [
    { brand => "A.1", PO => "1.a", supplier => "X" },
    { brand => "A.2", PO => "2.a", supplier => "X" },
    { brand => "B.1", PO => "1.b", supplier => "X" },
    { brand => "B.2", PO => "2.b", supplier => "X" },
    { brand => "B.3", PO => "1.c", supplier => "Y" },
];
my @sorted = map $_->[0], sort {
           $a->[1][0] cmp $b->[1][0]
        or $a->[1][1] <=> $b->[1][1]
        or $a->[1][2] <=> $b->[1][2]
        or $a->[1][3] cmp $b->[1][3]
    } map [ $_, [ map split( /[.-]/, $_, 2 ), @$_{qw(brand PO)} ] ],
    @$arr_ref;
print Dumper( \@sorted );

尝试使用品牌"A.10"来发现差异。

答案 2 :(得分:1)

尝试这种排序方法:

sub by_brand_or_po {
    my ($a_ba, $a_bn) = split /\.|-/, $a->{brand};
    my ($b_ba, $b_bn) = split /\.|-/, $b->{brand};

    my ($a_pa, $a_pn) = split /\.|-/, $a->{PO};
    my ($b_pa, $b_pn) = split /\.|-/, $b->{PO};

    return( $a_ba cmp $b_ba or $a_bn <=> $b_bn or
            $a_pa cmp $b_pa or $a_pn <=> $b_pn );
}

它优先考虑PO数字上的品牌alpha优于PO数字上的数字,并将分割为点或连字符。

答案 3 :(得分:0)

使用Sort::Key::Natural

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

my @sorted_by_brand = natkeysort { $_->{brand} } @data;
my @sorted_by_po = natkeysort { $_->{po} } @data;