打印时为什么散列键的顺序不同?(Why do hash keys have different order when printing?)

编程入门 行业动态 更新时间:2024-10-24 14:27:22
打印时为什么散列键的顺序不同?(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

然后当我重复运行代码时,我可以得到相同的输出。

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;

But the output is as follows:

$VAR1 = { 'key1' => 1, 'keyc' => 2, 'keyb' => 4, 'keya' => 3 }; $VAR2 = { 'keyb' => 4, 'keya' => 3, 'keyc' => 2, 'key1' => 1 };

i.e the hashes have a different and unexpected order. What's wrong with my 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)

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部分,以perlrun您可以控制此行为的方式以及为什么默认使用散列随机化的原因。

至少十年perl中的哈希并不能保证按键顺序。 最近,哈希随机化已成为一般安全“强化”工作的一部分。 散列随机化有很好的理由。 有关更多详细信息,请参阅perlsec对算法复杂性攻击的讨论 。 您将在Perl安全文档中注意到在perl-5.18中增加了进一步的增强功能 - 如果您看到与先前版本相比有不同的行为,可能是由于这些最新的变化。

除了以确定性的方式显式地对你的哈希键进行排序之外,还有其他一些方法可以用来订购你的哈希值: Hash::Ordered就是一个例子。 Hash::Ordered文档对许多其他模块的优点和缺点进行了很好的讨论。

虽然散列是以键值对排列的标量的“ 无序篮子 ” 数组标量的“ 有序序列[ 1 ] 。 “ 片 ”是访问“同时列表,数组或哈希的几个元素”的方式。 由于操作返回多个值的列表,因此一个切片使用@ sigil,并使用@我们得到“有序序列”。 结果是,在哈希上施加一种“顺序”的一种方式是使用切片来访问它:

# We want alphabetical disorder ... my %hashed = ( 1 => "z", 2 => "x", 3 => "y" ); for my $key ( keys %hashed ) { print $hashed{$key} } ; __END__ zyx

我们想要“ zxy ”而不是“ zxy ”。 为了在这个散列表上加上我们的任意版本的命令,我们首先需要认识到这里的罪魁祸首是keys %hashed ,它以随机顺序返回密钥。 解决方案是对ccurse的键进行sort ,并且在这个人为的例子中,我们将它们存储在@sort_order并使用它来根据我们想要的方式从散列中“分割出”我们想要的内容:

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

田田! 如果要将密钥和值存储在散列中,但以有序方式访问该数据,则片段可能很有用。 当你想要分片时记住“ @ ”; 正如perldata所说的那样:“你在散列片上使用'@' ... [因为]你回来了......列表”。 列表是有序的。


[ 1 ]哈希定义为“无序篮子”,数组定义为“有序序列”,来自Mike Friedman(FRIEDO)关于Perl中的数组与列表的优秀文章。

更多参考

比照 perlfaq -q我怎样才能始终保持我的散列排序? 除了创建一些真正有用的CPAN模块之外,GARU(Breno de Oliveira)发表了一篇关于哈希排序的优秀文章,其中全面介绍了最近的Perl开发和哈希随机化问题。 有关可以使用散列片做的整齐事情的更高级示例,请参阅Vince Veselosky的文章散列片可以替换循环 。

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.

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.

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.

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

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!! 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] The definitions of hashes as "unordered baskets" and arrays as "ordered sequence" are from Mike Friedman's (FRIEDO) excellent article on Arrays vs. Lists in Perl.

Further References

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.

更多推荐

本文发布于:2023-07-26 19:23:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1279898.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:顺序   hash   散列键   printing   order

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!