Perl - 哈希中的哈希 - 元素如何存储?

3

我是一个perl编程新手,从C语言转向perl编程感到很困难。非常感谢您的帮助。

#!/usr/bin/perl
use warnings;
use strict;
use Data::Dumper;

my %tgs;
$tgs{"0"}{"1"} = 01;
$tgs{"0"}{"2"} = 02;
$tgs{"0"}{"3"} = 03;
$tgs{"1"}{"1"} = 11;
$tgs{"1"}{"2"} = 12;
$tgs{"1"}{"3"} = 13;
$tgs{"2"}{"1"} = 21;
$tgs{"2"}{"2"} = 22;
$tgs{"2"}{"3"} = 23;


print Dumper(\%tgs);
exit(0);

输出是

$VAR1 = {
          '1' => {
                   '1' => 11,
                   '3' => 13,
                   '2' => 12
                 },
          '0' => {
                   '1' => 1,
                   '3' => 3,
                   '2' => 2
                 },
          '2' => {
                   '1' => 21,
                   '3' => 23,
                   '2' => 22
                 }
        };

我按照1、2、3的顺序输入了哈希值,但是当我打印输出时,它们的顺序变成了1、0、2。这是为什么?有没有办法可以控制它?我需要控制它,因为我将在foreach循环中读取这些数据,假定它们按0 1 2 3的顺序排列。


3
哈希表不会记住添加项目的顺序,它们只是从键到值的映射。 - Barmar
2
如果你关心顺序,请使用数组而不是哈希表。 - Barmar
1
这个perlfaq可能会有所帮助:如何让我的哈希表记住我放入元素的顺序? - devnull
2个回答

6

Perl无法保证哈希表中键的顺序。如果必须按特定顺序循环遍历元素,则可以执行以下操作:

for (sort keys %myhash) {
    print Dumper($tgs{$_});
}

如果键不能轻易排序,您可能需要使用具有映射的数组:

my %tgs;
$tgs{"0"}{"1"} = 01;
$tgs{"0"}{"2"} = 02;
$tgs{"0"}{"3"} = 03;
$tgs{"1"}{"1"} = 11;
$tgs{"1"}{"2"} = 12;
$tgs{"1"}{"3"} = 13;
$tgs{"2"}{"1"} = 21;
$tgs{"2"}{"2"} = 22;
$tgs{"2"}{"3"} = 23;

my @tag_keys = qw(1 2 3);

然后使用:

foreach (@tag_keys) {
    print Dumper($tgs{$_});
}

谢谢。这很有用。对于我的问题,我使用了'for'而不是像$tgs{i}{j}这样的“foreach”。:)为了在我的实际任务中使用数组和哈希,我需要更多的练习。尽管如此,还是要感谢提供的解决方案。 - Sandeep
1
在 Perl 中,forforeach 是可以互换使用的。 - Nathan Fellman

2
“Hashes”是无序的,正如你所发现的那样。如果你熟悉C语言中的“哈希表”,那么它基本上就是一样的——键通过哈希函数传递,哈希键通过生成的哈希值排序。如果哈希函数很好(确实如此),那么这个顺序就是有效随机的。此外,最近的Perl版本已经实现了随机化功能,这将导致哈希键的顺序每次运行程序时都不同。所以你真的不能指望哈希键有任何特定的顺序。
或者至少默认情况下是这样的。
长期以来,人们一直希望有一种记住插入顺序的哈希方式,于是有人发明了Tie::IxHash,它的作用就像一个普通的哈希表,只不过它还会附加一些元数据到每个键上以指示它们的顺序。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接