[英]In Perl, how do I print hash keys in order of their (numerical) values?
[英]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>
最后,在调用keys
和sort
函数之后。 按以下规则打印哈希键
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 :: Permute或Algorithm :: 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";
}
在查看您的代码示例时,我看到了一些您可能需要处理的事情。
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";
}
通过使用键从哈希中检索所有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.