如何对哈希数组的Perl数组进行排序?

时间:2010-03-24 18:16:48

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

@aoaoh;

$aoaoh[0][0]{21} = 31;
$aoaoh[0][0]{22} = 31;
$aoaoh[0][0]{23} = 17;

for $k (0 .. $#aoaoh) {
    for $i(0.. $#aoaoh) {
        for $val (keys %{$aoaoh[$i][$k]}) {
            print "$val=$aoaoh[$i][$k]{$val}\n";
        }
    }
}

输出结果为:

    22=31
    21=31
    23=17

但我希望它是

    21=31
    22=31
    23=17

请告诉我这是错的。

另外,我如何对值进行排序,以便将输出作为

    23=17 
    22=31
    21=31 (if 2 keys have same value then key with higher value come first)

4 个答案:

答案 0 :(得分:1)

听起来像你想要的那样:

for $val (sort keys %{$aoaoh[$i][$k]}) {

for $val (reverse sort keys %{$aoaoh[$i][$k]}) {

虽然从您的评论中看起来您不希望进行纯反向排序。您想要创建自己的排序功能:

for $val (sort {$aoaoh[$i][$k]->{$a} <=> $aoaoh[$i][$k]->{$b} || $a <=> $b} keys %{$aoaoh[$i][$k]}) {

答案 1 :(得分:0)

听起来你希望哈希按照定义的顺序返回键和值,而perl中没有这样的保证。

您可以实现更复杂的数据结构来处理某些排序,或者在显示中添加一些排序逻辑(而不是仅仅循环),或者加载模块以支持有序哈希,例如{ {3}}

我希望Tie :: Hash :: Indexed实现看起来像这样:

my @aoaoh;

use Tie::Hash::Indexed;
tie my %hash, 'Tie::Hash::Indexed';
$aoaoh[0][0] = \%hash;

$aoaoh[0][0]{21} = 31;
$aoaoh[0][0]{22} = 31;
$aoaoh[0][0]{23} = 17;

for $k (0 .. $#aoaoh) {
    for $i(0.. $#aoaoh) {
        for $val (keys %{$aoaoh[$i][$k]}) {
            print "$val=$aoaoh[$i][$k]{$val}\n";
        }
    }
}

答案 2 :(得分:0)

我回答了这个用户提出的另外两个完全相同的问题,但看起来这个问题会赢,所以我也在这里回答。

perlfaq4回答How do I sort an array by anything


为sort()提供比较函数(在perlfunc中的sort中描述):

@list = sort { $a <=> $b } @list;

默认排序函数是cmp,字符串比较,它将(1,2,10)排序为(1,10,2)。上面使用的&lt; =&gt;是数值比较运算符。

如果您需要复杂的功能来拉出要排序的部分,那么请不要在sort函数中执行此操作。首先将其拉出,因为对于同一元素,可以多次调用BLOCK排序。下面是一个示例,说明如何在每个项目的第一个数字后面拉出第一个单词,然后对这些单词不区分大小写。

@idx = ();
for (@data) {
    ($item) = /\d+\s*(\S+)/;
    push @idx, uc($item);
    }
@sorted = @data[ sort { $idx[$a] cmp $idx[$b] } 0 .. $#idx ];

也可以用这种方式编写,使用一种后来被称为Schwartzian变换的技巧:

@sorted = map  { $_->[0] }
    sort { $a->[1] cmp $b->[1] }
    map  { [ $_, uc( (/\d+\s*(\S+)/)[0]) ] } @data;

如果您需要对多个字段进行排序,以下范例很有用。

@sorted = sort {
    field1($a) <=> field1($b) ||
    field2($a) cmp field2($b) ||
    field3($a) cmp field3($b)
    } @data;

这可以方便地与上面给出的密钥的预先计算相结合。

有关此方法的更多信息,请参阅http://www.cpan.org/misc/olddoc/FMTEYEWTK.tgz中“远远超过您想知道的”集合中的排序文章。

另见perlfaq4中关于排序哈希的问题。

答案 3 :(得分:0)

Q1的答案是:

print "${$aoaoh[0][0]}{$_}=$_\n" for sort keys %{$aoaoh[0][0]};

可以写成:

for (sort keys %{$aoaoh[0][0]}) {
    print "${$aoaoh[0][0]}{$_}=$_\n"
}

Q2的答案:

print "$_->[1]=$_->[0]\n" for
map { [$_->[0], $_->[1]] }
sort { $a->[0] cmp $b->[0] }
map { [ ${$aoaoh[0][0]}{$_}, $_ ] } keys %{$aoaoh[0][0]};