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

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

问题描述

我想使用相同的键构建几个哈希值,并且当我打印它们时,键的顺序是相同的。因此,在下面的示例中, $ 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
        };

ie 哈希有不同的和意想不到的顺序。我的perl有什么问题?

i.e the hashes have a different and unexpected order. What's wrong with my 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哈希的密钥是不排序的顺序。我希望他们有相同的顺序,但是应该不需要排序顺序。我希望如果我再次运行代码,我可以得到相同的打印输出。

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.

而散列是以键值对排列的标量的无序篮, 切片是访问列表的几个元素,数组或一个哈希同时。一个切片使用 @ sigil,因为操作返回一个多个值的列表 - 并且使用 @ 我们得到有序序列。结果是,通过使用切片来访问它,在哈希中强加一种命令的一种方式是:

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 not zyx 。为了强加我们在这个哈希的任意版本的顺序,我们首先需要认识到这里的罪魁祸首是$ code> 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

Tada!当您希望将密钥和值存储在哈希中时,切片可能很有用,但以有序的方式访问该数据。记住 @ ,当你想分片哈希;如 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天全站免登陆