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

打印Perl哈希时,什么决定键的顺序?,perl,hash,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 %s

基于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>
最后,在调用
排序
函数之后。哈希键打印遵循以下规则

2.5hellobar12.4bettybyefoo35wilma1.72e+030
元素(几乎可以肯定)是按照它们在哈希表本身(内部)中出现的顺序打印出来的——即基于它们的键的哈希值


如果您非常关心顺序,那么遵循的一般规则是使用哈希表以外的内容。

哈希表的元素是按其内部顺序打印出来的,不能依赖这些元素,并且会随着元素的添加和删除而改变。如果您需要以某种顺序排列散列的所有元素,请对键进行排序,并使用该列表对散列进行索引

如果您正在寻找一个按顺序保存其元素的结构,可以使用数组,也可以在CPAN上使用一个有序散列


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

对于大多数实际目的,散列表(不仅仅是Perl散列变量,而是一般的散列表)的顺序可以视为随机的

实际上,根据散列实现,顺序实际上可能是确定的。(也就是说,如果您多次运行该程序,每次都将相同的项目以相同的顺序放入哈希表中,它们每次都将以相同的顺序存储。)我知道Perl哈希过去有这个特性,但我不确定当前的版本。在任何情况下,哈希键顺序都不是在需要随机性的情况下使用的随机性的可靠来源

简短版本,然后:


如果您关心顺序(或缺少顺序),请不要使用散列。如果你想要一个固定的顺序,它将实际上是随机的,如果你想要一个随机的顺序,它将实际上是固定的。

我检查了你的代码,并做了一些注释,我认为你会觉得有用

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";
}
通过查看您的代码示例,我看到了一些您可能需要解决的问题

  • 如何使用
    for
    while
    等循环结构来减少重复代码
  • 如何使用变量插值

顺便说一句,我很高兴看到你在做基础工作,提高你的代码质量。这项时间投资会有回报的。继续做好工作。

散列不定义排序属性。事情发生的顺序是不可预测的。

哈希值(不一定)是以排序方式检索的。如果要对它们进行排序,您必须自己进行排序:

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";
}
使用
从散列中检索所有键,然后使用
排序
对它们进行排序。是的,我知道,那个疯狂的拉里·沃尔,谁会想到这样称呼他们呢?:-)

这将产生:

a -> 1
b -> 2
c -> 3
d -> 4
发件人:

散列的键以明显的随机顺序返回。在未来的Perl版本中,实际的随机顺序可能会发生更改,但可以保证其顺序与值或每个函数生成的顺序相同(假定哈希未被修改)。由于Perl 5.8.1,出于安全原因,即使在不同的Perl运行之间,顺序也是不同的(请参阅)

Perl从未保证哈希键的任何顺序,而且在Perl5的生命周期中,顺序已经改变了好几次。此外,哈希键的顺序一直并将继续受到插入顺序的影响

还请注意,虽然散列元素的顺序可能是随机的,但这种“伪顺序”不应用于诸如随机洗牌列表之类的应用程序(请参阅自Perl 5.8.0以来的标准核心模块;或CPAN模块),或用于生成置换(例如使用CPAN模块或),或用于任何加密应用程序



注意:因为您是在列表上下文中计算哈希,所以至少可以保证每个键后面都跟有相应的值;e、 g.您永远不会看到
a4b3c2d1的输出

如果您疯了,哈希中没有重复的值,并且您需要对这些值进行排序,您可以对其调用reverse

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

print $_ for sort keys %reverse_hash;

警告是唯一值部分,重复项将被覆盖,并且只有一个值将进入

嗨,Jerry,如何检测它们在哈希表中(内部)出现的顺序。我没有安装IDE,这意味着我无法在运行时调试它。而且索引键不是基于数字的,我也不能按照索引键值打印。嗨,杰瑞,我更新了我的帖子。我将散列值分配给一个数组,我可以打印和监视顺序。但我仍然认为顺序非常复杂。Nano,使用
功能获取键列表。它们很可能与它们存储在散列中的顺序相同,尽管没有保证。如果顺序很重要,那么您首先不应该使用散列,或者应该使用
keys
函数来获取列表,将项目按所需顺序排列,然后在该列表中循环,访问每个相应的散列项目。例如:
my@keys=keys%hash;对于我的$k(sort@keys){print$k,$hash{$k};}
有关更多信息,请阅读
keys
、阅读perlfaq4或发布新问题。Als