假设你有一个数组@a = qw/ a b c d/;
和哈希%a = ('a' => 1, 'b' => 1, 'c' => 1, 'd' => 1);
是否有任何情况下创建数组版本比创建哈希更好(除非必须迭代所有值,如
for (@a){
....
在这种情况下,如果使用散列,则必须使用keys %a
?因为测试特定值是否在散列中总是比在数组中这样做更有效,所以更正吗?
答案 0 :(得分:8)
有许多新兴属性。首先,
答案 1 :(得分:3)
数组是有序的值列表。它们可以包含重复值。
@array = qw(a b c a);
哈希是密钥(必须是唯一的)和值(可以复制)之间的映射。哈希(有效地)无序,这意味着密钥以明显随机的顺序而不是输入的顺序出现。
%hash = (a => 1, b => 2, c => 3);
只有关键很重要时,哈希也可以用作集合。集合是无序的,只包含唯一的“值”(散列键)。
%set = (a => undef, b => undef, c => undef);
使用哪一个取决于您的数据和算法。在订单很重要时使用数组(特别是如果您无法排序以获取订单)或者可能存在重复值。当值必须唯一且不关心顺序时,使用集合(即使用散列作为集合)。当唯一性很重要时使用哈希,顺序不(或很容易排序),查找基于任意值而不是整数。
您可以组合数组和散列(通过引用)来创建任意复杂的数据结构。
@aoa = ([1, 2, 3], [4, 5, 6]); # array of arrays ("2D" array)
%hoh = (a => { x => 1 }, b => { x => 2 }); # hash of hashes
@aoh = ({a => 1, b => 2}, {a => 3, b => 4}); # array of hashes
%hoa = (a => [1, 2], b => [3, 4]); # hash of arrays
...etc.
答案 2 :(得分:2)
这是关于使用数字作为哈希键。它并没有直接回答这个问题,因为它没有比较数组提供的设施,但我认为这是放置信息的好地方。
假设使用像这样的代码构建具有十个元素的哈希
use strict;
use warnings;
my %hash;
my $n = 1000;
for (1 .. 10) {
$hash{$n} = 1;
$n *= 1000;
}
然后我们查询它,寻找10的幂的密钥。当然,将整数乘以10的最简单方法是添加零,因此可以写
my $m = '1';
for (1 .. 100) {
print $m, "\n" if $hash{$m};
$m .= 0;
}
有输出
1000
1000000
1000000000
1000000000000
1000000000000000
1000000000000000000
我们输入了十个元素,但这只显示了六个元素。发生了什么事?我们来看看哈希中的内容。
use Data::Dump;
dd \%hash;
并输出
{
"1000" => 1,
"1000000" => 1,
"1000000000" => 1,
"1000000000000" => 1,
"1000000000000000" => 1,
"1000000000000000000" => 1,
"1e+021" => 1,
"1e+024" => 1,
"1e+027" => 1,
"1e+030" => 1,
}
因此哈希不会使用我们想象的密钥。它以一种试图模仿的愚蠢方式对数字进行字符串化。
对于一个稍微更实际的例子,假设我们有一些圈子,并希望按区域收集。显而易见的是将该区域用作哈希键,就像这个程序一样,可以创建100,000个随机整数直径高达1800万的圆圈。
use strict;
use warnings;
use 5.010;
package Circle;
use Math::Trig 'pi';
sub new {
my $class = shift;
my $self = { radius => shift };
bless $self, $class;
}
sub area {
my $self = shift;
my $radius = $self->{radius};
pi * $radius * $radius;
}
package main;
my %circles;
for (1 .. 100_000) {
my $circle = Circle->new(int rand 18_000_000);
push @{ $circles{$circle->area} }, $circle;
}
现在让我们看看有多少哈希键使用科学记数法
say scalar grep /e/, keys %circles;
说(当然是随机的)
861
因此,如果我们将数字指定为哈希索引,那么确实不知道 string perl将使用什么的整洁方式。
答案 3 :(得分:1)
在Perl中,@array
是由整数(正数和负数)访问的值($v1, $v2, ...)
的有序列表,
而%hash是'key =>的无序列表通过字符串访问的值'(k1 => $v1, k2 => $v2, ...)
。
CPAN上有模块实现有序哈希,例如:Hash::Ordered和Tie::IxHash
你可能想要使用一个数组,当你订购'items'时可能也是一个很好的数字 使用%哈希并对键和/或值进行排序将是低效的。