为什么哈希键在打印时有不同的顺序?
Why do hash keys have different order when printing?
我想使用相同的密钥构建多个散列,并在打印时让这些密钥具有相同的顺序。因此,在下面的示例中,$hash1
和 $hash2
的键应始终具有相同的顺序,但在创建哈希时无需保留该顺序。
use Data::Dumper;
my $hash1 = {
keyc => 2,
key1 => 1,
keya => 3,
keyb => 4,
};
my $hash2 = {
keyc => 2,
key1 => 1,
keya => 3,
keyb => 4,
};
print Dumper $hash1, $hash2;
但是输出如下:
$VAR1 = {
'key1' => 1,
'keyc' => 2,
'keyb' => 4,
'keya' => 3
};
$VAR2 = {
'keyb' => 4,
'keya' => 3,
'keyc' => 2,
'key1' => 1
};
即 哈希值具有不同的意外顺序。我的 perl 有什么问题?
我的 perl 版本是:
This is perl 5, version 18, subversion 2 (v5.18.2) built for darwin-thread-multi-2level
(with 2 registered patches, see perl -V for more detail)
注意:我知道perl hash的键是无序的。我希望他们有相同的顺序,但不需要排序的顺序。我希望如果我再次 运行 代码,我可以获得相同的打印输出。
根据答案的建议,我设置了两个环境变量:
PERL_HASH_SEED=0x00 PERL_PERTURB_KEYS=0
然后当我重复运行代码时我可以得到相同的输出。
您的 perl 没有问题,散列未排序。
如果你想按键排序,你需要做类似的事情:
foreach my $key (sort keys %hash1) {
print $key, $hash1{$key};
}
hash2 也一样...
打印哈希时,有几个不同的相关顺序概念:"insertion order"、"sort order" 和 "random"。请参阅 ENVIRONMENT section of the perlrun
文档以了解如何控制此行为以及默认使用哈希随机化的原因。
至少十年来,perl 中的哈希并没有保证键的顺序。最近,哈希随机化已成为一般安全 "hardening" 工作的一部分。哈希值被随机化是有充分理由的。有关详细信息,请参阅 perlsec
discussion of algorithmic complexity attacks。您会在 Perl 安全文档中注意到 perl-5.18
中添加了进一步的增强功能 - 如果您看到与以前版本相比不同的行为,则可能是由于最近的这些更改。
此外,sorting your hash keys in a deterministic way, there are other approaches you can take to ordering your hashes: Hash::Ordered
就是一个例子。 Hash::Ordered
文档对许多其他模块的优缺点进行了很好的讨论。
虽然哈希是按键值对排列的标量的“无序篮子”;数组 是 标量 [1][= 的“有序序列” 71=]。 “slice”是访问 "several elements of a list, an array, or a hash simultaneously" 的方式。切片使用 @
标记,因为操作 returns 是多个值的列表 - 使用 @
我们得到 "ordered sequence"。结果是在散列上施加一种 "order" 的一种方法是使用切片来访问它:
# We want alphabetical disorder ...
my %hashed = ( 1 => "z", 2 => "x", 3 => "y" );
for my $key ( keys %hashed ) { print $hashed{$key} } ;
__END__
zyx
我们想要“zxy
”而不是“zyx
”。为了将我们的任意版本的顺序强加于此哈希,我们首先需要认识到这里的罪魁祸首是 keys %hashed
,其中 returns 键的顺序是随机的。解决方案是使用 ccurse 的 sort
键,在这个人为的示例中,我们将它们存储在 @sort_order
中,并使用它来 "slice" 从哈希中提取我们想要的内容,我们想要的方式:
my @sort_order = sort keys %hashed ;
print @hashed{@sort_order} ;
__END__
zxy
多田!!当您想要将键和值存储在散列中但以有序方式访问该数据时,切片会很有用。当你想对散列进行切片时,请记住“@
”;正如 perldata
所说:"you use an '@'
... on a hash slice ... [because] you are getting back ...a list"。列表是有序的。
[1] 哈希 "unordered baskets" 和数组 "ordered sequence" 的定义来自 Mike Friedman (FRIEDO) 关于 Arrays vs. Lists in Perl 的优秀文章。
更多参考资料
- cf.
perlfaq
-q How can I always keep my hash sorted?
- 除了创建许多非常有用的 CPAN 模块之外,GARU (Breno de Oliveira) 还发布了an excellent article on hash ordering,其中彻底涵盖了最近的 Perl 开发和哈希随机化问题。
- 有关您可以使用散列切片做的整洁事情的更多高级示例,请参阅 Vince Veselosky 的文章 Hash slices can replace loops。
G。 Cito 的回答是正确的。但是,如果您想要 Data::Dumper 的排序输出,您可以这样做:
use Data::Dumper;
my $hash1 = {
keyc => 2,
key1 => 1,
keya => 3,
keyb => 4,
};
my $hash2 = {
keyc => 2,
key1 => 1,
keya => 3,
keyb => 4,
};
my $dumper = Data::Dumper->new([$hash1, $hash2]);
$dumper->Sortkeys(1);
print $dumper->Dump;
我想使用相同的密钥构建多个散列,并在打印时让这些密钥具有相同的顺序。因此,在下面的示例中,$hash1
和 $hash2
的键应始终具有相同的顺序,但在创建哈希时无需保留该顺序。
use Data::Dumper;
my $hash1 = {
keyc => 2,
key1 => 1,
keya => 3,
keyb => 4,
};
my $hash2 = {
keyc => 2,
key1 => 1,
keya => 3,
keyb => 4,
};
print Dumper $hash1, $hash2;
但是输出如下:
$VAR1 = {
'key1' => 1,
'keyc' => 2,
'keyb' => 4,
'keya' => 3
};
$VAR2 = {
'keyb' => 4,
'keya' => 3,
'keyc' => 2,
'key1' => 1
};
即 哈希值具有不同的意外顺序。我的 perl 有什么问题?
我的 perl 版本是:
This is perl 5, version 18, subversion 2 (v5.18.2) built for darwin-thread-multi-2level
(with 2 registered patches, see perl -V for more detail)
注意:我知道perl hash的键是无序的。我希望他们有相同的顺序,但不需要排序的顺序。我希望如果我再次 运行 代码,我可以获得相同的打印输出。
根据答案的建议,我设置了两个环境变量:
PERL_HASH_SEED=0x00 PERL_PERTURB_KEYS=0
然后当我重复运行代码时我可以得到相同的输出。
您的 perl 没有问题,散列未排序。
如果你想按键排序,你需要做类似的事情:
foreach my $key (sort keys %hash1) {
print $key, $hash1{$key};
}
hash2 也一样...
打印哈希时,有几个不同的相关顺序概念:"insertion order"、"sort order" 和 "random"。请参阅 ENVIRONMENT section of the perlrun
文档以了解如何控制此行为以及默认使用哈希随机化的原因。
至少十年来,perl 中的哈希并没有保证键的顺序。最近,哈希随机化已成为一般安全 "hardening" 工作的一部分。哈希值被随机化是有充分理由的。有关详细信息,请参阅 perlsec
discussion of algorithmic complexity attacks。您会在 Perl 安全文档中注意到 perl-5.18
中添加了进一步的增强功能 - 如果您看到与以前版本相比不同的行为,则可能是由于最近的这些更改。
此外,sorting your hash keys in a deterministic way, there are other approaches you can take to ordering your hashes: Hash::Ordered
就是一个例子。 Hash::Ordered
文档对许多其他模块的优缺点进行了很好的讨论。
虽然哈希是按键值对排列的标量的“无序篮子”;数组 是 标量 [1][= 的“有序序列” 71=]。 “slice”是访问 "several elements of a list, an array, or a hash simultaneously" 的方式。切片使用 @
标记,因为操作 returns 是多个值的列表 - 使用 @
我们得到 "ordered sequence"。结果是在散列上施加一种 "order" 的一种方法是使用切片来访问它:
# We want alphabetical disorder ...
my %hashed = ( 1 => "z", 2 => "x", 3 => "y" );
for my $key ( keys %hashed ) { print $hashed{$key} } ;
__END__
zyx
我们想要“zxy
”而不是“zyx
”。为了将我们的任意版本的顺序强加于此哈希,我们首先需要认识到这里的罪魁祸首是 keys %hashed
,其中 returns 键的顺序是随机的。解决方案是使用 ccurse 的 sort
键,在这个人为的示例中,我们将它们存储在 @sort_order
中,并使用它来 "slice" 从哈希中提取我们想要的内容,我们想要的方式:
my @sort_order = sort keys %hashed ;
print @hashed{@sort_order} ;
__END__
zxy
多田!!当您想要将键和值存储在散列中但以有序方式访问该数据时,切片会很有用。当你想对散列进行切片时,请记住“@
”;正如 perldata
所说:"you use an '@'
... on a hash slice ... [because] you are getting back ...a list"。列表是有序的。
[1] 哈希 "unordered baskets" 和数组 "ordered sequence" 的定义来自 Mike Friedman (FRIEDO) 关于 Arrays vs. Lists in Perl 的优秀文章。
更多参考资料
- cf.
perlfaq
-q How can I always keep my hash sorted? - 除了创建许多非常有用的 CPAN 模块之外,GARU (Breno de Oliveira) 还发布了an excellent article on hash ordering,其中彻底涵盖了最近的 Perl 开发和哈希随机化问题。
- 有关您可以使用散列切片做的整洁事情的更多高级示例,请参阅 Vince Veselosky 的文章 Hash slices can replace loops。
G。 Cito 的回答是正确的。但是,如果您想要 Data::Dumper 的排序输出,您可以这样做:
use Data::Dumper;
my $hash1 = {
keyc => 2,
key1 => 1,
keya => 3,
keyb => 4,
};
my $hash2 = {
keyc => 2,
key1 => 1,
keya => 3,
keyb => 4,
};
my $dumper = Data::Dumper->new([$hash1, $hash2]);
$dumper->Sortkeys(1);
print $dumper->Dump;