繁体   English   中英

当我打印Perl哈希时,什么决定了键的顺序?

[英]What decides the order of keys when I print a Perl hash?

基于activePerl 5.8

#!C:\Perl\bin\perl.exe
use strict;
use warnings;

# declare a new hash
my %some_hash;

%some_hash = ("foo", 35, "bar", 12.4, 2.5, "hello",
      "wilma", 1.72e30, "betty", "bye\n");

my @any_array;
@any_array = %some_hash;

print %some_hash;
print "\n";
print @any_array;
print "\n";
print $any_array[0];
print "\n";
print $any_array[1];
print "\n";
print $any_array[2];
print "\n";
print $any_array[3];
print "\n";
print $any_array[4];
print "\n";
print $any_array[5];
print "\n";
print $any_array[6];
print "\n";
print $any_array[7];
print "\n";
print $any_array[8];
print "\n";
print $any_array[9];

这样输出

D:\learning\perl>test.pl
bettybye
bar12.4wilma1.72e+030foo352.5hello
bettybye
bar12.4wilma1.72e+030foo352.5hello
betty
bye

bar
12.4
wilma
1.72e+030
foo
35
2.5
hello
D:\learning\perl>

是什么决定了示例代码中元素的打印顺序?

在Perl中打印混合(字符串,数字)哈希时要遵循的任何规则? 谢谢。

bar12.4wilma1.72e+030foo352.5hello

[更新]

在你们的帮助下,我更新了以下代码。

#!C:\Perl\bin\perl.exe
use strict;
use warnings;

# declare a new hash
my %some_hash;

%some_hash = ("foo", 35, "bar", 12.4, 2.5, "hello",
      "wilma", 1.72e30, "betty", "bye");

my @any_array;
@any_array = %some_hash;

print %some_hash;
print "\n";
print "\n";
print @any_array;
print "\n";
print "\n";

my @keys;
@keys = keys %some_hash;
for my $k (sort @keys)
{
    print $k, $some_hash{$k};
}

输出

D:\learning\perl>test.pl
bettybyebar12.4wilma1.72e+030foo352.5hello

bettybyebar12.4wilma1.72e+030foo352.5hello

2.5hellobar12.4bettybyefoo35wilma1.72e+030
D:\learning\perl>

最后,在调用keyssort函数之后。 按以下规则打印哈希键

2.5hellobar12.4bettybyefoo35wilma1.72e+030

哈希的元素以其内部顺序打印出来,无法依赖,并且会随着元素的添加和删除而发生变化。 如果您需要某种顺序的哈希值的所有元素,请对键进行排序,然后使用该列表为哈希值编制索引。

如果要查找按顺序保留其元素的结构,请使用数组或在CPAN上使用有序哈希之一。

您可以从列表上下文哈希扩展中依赖的唯一顺序是键=>值对将在一起。

perldoc -f键

哈希键显然是随机顺序返回的。 实际的随机顺序在Perl的未来版本中可能会发生变化,但是可以保证与值或每个函数产生的顺序相同(假定哈希值未修改)。 从Perl 5.8.1开始,出于安全原因,即使在不同的Perl运行之间,顺序也有所不同(请参阅perlsec中的算法复杂性攻击 )。

...

Perl从未保证哈希键的任何顺序,并且在Perl 5的生命周期中,该顺序已经改变了几次。而且,哈希键的顺序始终受插入顺序的影响,并将继续受到其影响。

还要注意,尽管哈希元素的顺序可能是随机的,但这种“伪排序”不应用于诸如随机排序列表之类的应用(为此,请使用List :: Util :: shuffle(),请参见List :: Util ,从Perl 5.8.0开始的标准核心模块;或CPAN模块Algorithm :: Numerical :: Shuffle ),或用于生成置换(例如使用CPAN模块Algorithm :: PermuteAlgorithm :: FastPermute ),或用于任何加密应用程序。


注意:由于您要在列表上下文中评估哈希, 因此至少可以确保每个键后面都带有对应的值; 例如,您将永远不会看到a 4 b 3 c 2 d 1

我仔细阅读了您的代码,并做了一些说明,认为对您有所帮助。

use strict;
use warnings;

# declare a new hash and initialize it at the same time
my %some_hash = (
    foo   => 35,       # use the fat-comma or '=>' operator, it quotes the left side
    bar   => 12.4,     
    2.5   => "hello",
    wilma => 1.72e30,
    betty => "bye",    # perl ignores trailing commas, 
                       # the final comma makes adding items to the end of the list less bug prone.
);

my @any_array = %some_hash; # Hash is expanded into a list of key/value pairs.

print "$_ => $some_hash{$_}\n" 
    for keys %some_hash;

print "\n\n",              # You can print multiple newlines in one string.
      "@any_array\n\n";    # print takes a list of things to print.

# In print @foo; @foo is expanded into a list of items to print.  
# There is no separator between the members of @foo in the output.

# However print "@foo"; interpolates @foo into a string. 
# It inserts spaces between the members of the arrays.


# This is the block form of 'for'
for my $k (sort keys %some_hash)
{
    # Interpolating the variables into a string makes it easier to read the output.
    print "$k => $some_hash{$k}\n";
}

哈希通过字符串键提供无序访问数据的功能。

数组提供对有序数据的访问。 通过使用数字索引可以进行随机访问。

如果需要保留一组值的顺序,请使用数组。 如果需要通过关联的名称查找组的成员,请使用哈希。

如果您需要同时执行这两种操作,则可以同时使用这两种结构:

# Keep an array of sorted hash keys.
my @sorted_items = qw( first second third fourth );

# Store the actual data in the hash.
my %item;
@item{ @sorted_items } = 1..4;  # This is called a hash slice.  
                                # It allows you to access a list of hash elements.
                                # This can be a very powerful way to work with hashes.

# random access
print "third => $item{third}\n";


# When you need to access the data in order, iterate over
# the array of sorted hash keys.  Use the keys to access the
# data in the hash.

# ordered access
for my $name ( @sorted_items ) {
    print "$name => $item{$name}\n";
}

在查看您的代码示例时,我看到了一些您可能需要处理的事情。

  • forwhile类的循环结构如何用于减少重复代码。
  • 如何使用变量插值

顺便说一句,很高兴看到您在基础方面进行工作并提高代码质量。 这种时间上的投资将得到回报。 保持良好的工作。

元素(几乎可以肯定)是按照它们在哈希表本身中(内部)出现的顺序打印出来的,即基于其键的哈希值。

遵循的一般规则是,如果您非常关注顺序,则可以使用哈希表以外的其他方法。

哈希不能(有必要)以排序的方式检索。 如果要对它们进行排序,则必须自己进行:

use strict;
use warnings;

my %hash = ("a" => 1, "b" => 2, "c" => 3, "d" => 4);

for my $i (sort keys %hash) {
    print "$i -> $hash{$i}\n";
}

通过使用键从哈希中检索所有keys ,然后使用sort对其进行sort 是的,我知道,那个疯狂的拉里·沃尔(Larry Wall)家伙,曾经想过要称呼他们吗? :-)

输出:

a -> 1
b -> 2
c -> 3
d -> 4

对于大多数实际目的,可以将哈希表(不仅是Perl哈希变量,而且通常是哈希表)的顺序视为随机的。

实际上,根据哈希实现方式,顺序实际上可能是确定性的。 (即,如果您多次运行该程序,并且每次都以相同的顺序将相同的项放入哈希表中,那么它们每次将以相同的顺序进行存储。)我知道Perl哈希曾经具有这种特性,但是我不确定当前版本。 无论如何,在需要随机性的情况下,哈希键顺序不是可靠的随机性来源。

短版,然后:

如果您关心顺序(或缺少顺序),请不要使用哈希。 如果您想要一个固定的订单,那么它实际上是随机的;如果您想要一个随机的订单,那么它将会被有效地固定。

哈希没有定义任何排序属性。 事物出现的顺序将是不可预测的。

而且,如果您发疯了,并且哈希中没有重复的值,并且需要对值进行排序,则可以对其调用反向。

my %hash = ("a" => 1, "b" => 2, "c" => 3, "d" => 4);
my %reverse_hash = reverse %hash;

print $_ for sort keys %reverse_hash;

注意是唯一值部分,重复项将被覆盖,只有一个值会进入。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM