为什么打印时哈希键的顺序不同? [英] Why do hash keys have different order when printing?

查看:30
本文介绍了为什么打印时哈希键的顺序不同?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想使用相同的键构建多个散列,并且在打印它们时键具有相同的顺序.因此,在下面的示例中,$hash1$hash2 的键应该始终具有相同的顺序,但在创建哈希时应该不需要保持该顺序.

I want to build several hashes using the same keys and for the keys to have the same order when I print them. So, in the example below, the keys of $hash1 and $hash2 should always have the same order, but there should be no need to keep that order when creating the hash.

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
        };

i.e 散列具有不同且意外的顺序.我的 perl 有什么问题?

i.e the hashes have a different and unexpected order. What's wrong with my perl?

我的 perl 版本是:

My perl version is:

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 的键是未排序的.我希望它们具有相同的顺序,但应该不需要排序顺序.我希望如果我再次运行代码,我可以得到相同的打印输出.

Notice: I know that keys of perl hash is unsorted order. I want they have the same order, but there should be no need to have the sorted order. I hope that I can get the same print output if I run the code again.

根据答案的建议,我设置了两个环境变量:

Following advice from answers, I set two environment variables:

PERL_HASH_SEED=0x00 PERL_PERTURB_KEYS=0

然后我可以在重复运行代码时得到相同的输出.

Then I can get the same output when I run the code repeatedly.

推荐答案

在打印散列时,有几个不同的相关顺序概念:插入顺序"、排序顺序"和随机".请参阅 perlrun 文档的 ENVIRONMENT 部分以了解有关控制此行为的方法以及默认使用哈希随机化的原因.

When printing a hash there are a few different notions of order that are relevant: "insertion order", "sort order" and "random". See the ENVIRONMENT section of the perlrun documentation for a discussion of ways you can control this behavior and for the reasons why the default is to use hash randomization.

至少十年来,perl 中的散列无法保证密钥顺序.最近,散列随机化已成为一般安全强化"工作的一部分.散列被随机化是有充分理由的.有关详细信息,请参阅 perlsec 对算法复杂性攻击的讨论.您会在 Perl 安全文档中注意到 perl-5.18 中添加了进一步的增强功能 - 如果您看到与以前版本相比的不同行为,则可能是由于这些最近的更改.

For at least a decade hashes in perl have not guaranteed key order. More recently, hash randomization has been part of a general security "hardening" effort. There are good reasons for hashes to be randomized. For more details see the perlsec discussion of algorithmic complexity attacks. You'll note in the Perl security documentation that further enhancements were added in perl-5.18 - if you are seeing a different behavior compared to previous versions it may be due to these most recent changes.

除了明确以确定性方式对您的哈希键进行排序之外,您还有其他方法可以对您的哈希进行排序:Hash::Ordered 是其中之一例子.Hash::Ordered 文档很好地讨论了许多其他模块的优缺点.

Besides explicitly sorting your hash keys in a deterministic way, there are other approaches you can take to ordering your hashes: Hash::Ordered is one example. The Hash::Ordered documentation has a good discussion of the pros and cons of a number of other modules.

虽然散列是按键值对排列的无序篮子"标量;数组一个有序序列"的标量[1].slice" 是访问列表、数组或同时散列".切片使用 @ 符号,因为操作返回多个值的列表 - 使用 @ 我们得到有序序列".结果是对散列施加一种顺序"的一种方法是使用切片来访问它:

While a hash is an "unordered basket" of scalars arranged in key-value pairs; an array is an "ordered sequence" of scalars [1]. A "slice" is way of accessing "several elements of a list, an array, or a hash simultaneously". A slice uses the @ sigil since the operation returns a list of multiple values - and with @ we get "ordered sequence". The upshot is that one way to impose a kind of "order" on a hash is by using a slice to access it:

# 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 它以随机顺序返回键.解决方案是对 ccurse 的键进行sort,在这个人为的例子中,我们将它们存储在 @sort_order 中,并使用它从散列中切出"我们想要的东西,方式我们想要它:

We want "zxy" not "zyx". To impose our arbitrary version of order on this hash we first need to recognize that culprit here is keys %hashed which returns the keys in random order. The solution is to sort keys of ccurse and in this contrived example we store them in @sort_order and use it to "slice" out what we want from the hash, the way we want it:

my @sort_order = sort keys %hashed ;
print @hashed{@sort_order} ;
__END__
zxy

多田!!当您想在散列中存储键和值但以有序方式访问该数据时,切片会很有用.当你想对散列进行切片时,请记住@";正如 perldata 所说:您使用 '@' ... 在散列切片上 ... [因为] 您正在返回 ...一个列表".并且列表是有序的.

Tada!! Slices can be useful when you want to store keys and values in a hash but access that data in an ordered way. Remember the "@" when you want to slice a hash; as perldata puts it: "you use an '@' ... on a hash slice ... [because] you are getting back ...a list". And lists are orderly.

[1] 散列定义为无序篮子",数组定义为有序序列"来自 Mike Friedman (FRIEDO) 关于 Perl 中的数组与列表.

进一步参考

  • cf. perlfaq -q How can I always keep my hash sorted?
  • In addtion to creating a number of really useful CPAN modules, GARU (Breno de Oliveira) published an excellent article on hash ordering that thoroughly covers recent Perl development and hash randomization issues.
  • For more advanced examples of neat things you can do with hash slices see Vince Veselosky's article Hash slices can replace loops.

这篇关于为什么打印时哈希键的顺序不同?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆