Arrays 在Perl中,什么时候使用数组而不是哈希更好?
假设你有一个数组Arrays 在Perl中,什么时候使用数组而不是哈希更好?,arrays,perl,hash,Arrays,Perl,Hash,假设你有一个数组@a=qw/a b c d/ 和散列%a=('a'=>1,'b'=>1,'c'=>1,'d'=>1) 是否存在创建数组版本比创建散列更好的情况(除了必须迭代所有值,如 for (@a){ .... 在这种情况下,如果使用哈希,则必须使用键%a)?因为测试特定值是否在散列中总是比在数组中更有效,对吗 数组由数字索引 哈希由字符串设置键 数组中存在最高索引的所有索引 散列索引很少。(例如,“a”和“c”可以在没有“b”的情况下存在。) 有许多紧急属性。主要是
@a=qw/a b c d/代码>
和散列%a=('a'=>1,'b'=>1,'c'=>1,'d'=>1)代码>
是否存在创建数组版本比创建散列更好的情况(除了必须迭代所有值,如
for (@a){
....
在这种情况下,如果使用哈希,则必须使用键%a
)?因为测试特定值是否在散列中总是比在数组中更有效,对吗
- 数组由数字索引
- 哈希由字符串设置键
- 数组中存在最高索引的所有索引
- 散列索引很少。(例如,“a”和“c”可以在没有“b”的情况下存在。)
有许多紧急属性。主要是
- 数组可用于存储有序列表
- 以这种方式使用哈希将是一种低效的做法
- 除非是索引最高的元素,否则无法从数组中删除元素
- 您可以从使用数组实现的有序列表中删除,尽管删除第一个或最后一个元素以外的元素效率很低
- 可以从散列中删除元素,而且效率很高
数组是值的有序列表。它们可以包含重复的值
@array = qw(a b c a);
散列是键(必须是唯一的)和值(可以复制)之间的映射。散列(实际上)是无序的,这意味着密钥的出现顺序显然是随机的,而不是它们的输入顺序
%hash = (a => 1, b => 2, c => 3);
当只有键重要时,哈希也可以用作集合。集合是无序的,只包含唯一的“值”(散列的键)
使用哪一种取决于您的数据和算法。当顺序很重要时(特别是当您无法排序以导出顺序时),或者如果可能存在重复值,请使用数组。当值必须是唯一的且不关心顺序时,使用集合(即使用哈希作为集合)。当唯一性很重要,顺序不重要(或者很容易排序),并且查找基于任意值而不是整数时,请使用哈希
您可以组合数组和散列(通过引用)来创建任意复杂的数据结构
@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.
这是关于使用数字作为散列键的。它没有直接回答这个问题,因为它没有比较阵列提供的功能,但我认为它将是一个放置信息的好地方
假设一个包含十个元素的散列是使用如下代码构建的
use strict;
use warnings;
my %hash;
my $n = 1000;
for (1 .. 10) {
$hash{$n} = 1;
$n *= 1000;
}
然后我们查询它,寻找十次幂的键。当然,将一个整数乘以十的最简单方法是加一个零,所以写起来很好
my $m = '1';
for (1 .. 100) {
print $m, "\n" if $hash{$m};
$m .= 0;
}
哪个有输出
1000
1000000
1000000000
1000000000000
1000000000000000
1000000000000000000
我们输入了十个元素,但这只显示了六个。发生了什么事?让我们看一下哈希中的内容。< /P>
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,
}
所以散列没有使用我们想象的键。它以一种试图模仿的愚蠢方式对数字进行严格限制
举一个稍微实际一点的例子,假设我们有一些圆,希望按面积收集成一组。最明显的是将区域用作散列键,就像这个程序创建100000个圆,随机整数直径高达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;
上面说(当然是随机的)
因此,如果我们指定一个数字作为散列索引,实际上没有一种清晰的方法来知道perl将使用什么字符串。在perl中,@array
是一个由整数(正数和负数)访问的有序值列表,
%hash是一个无序的“key=>value”对列表(k1=>$v1,k2=>$v2,…)
,由字符串访问
CPAN上有一些模块实现有序散列,如:和
例如,当您订购了大量的“项目”时,您可能希望使用数组
使用%散列并对键和/或值进行排序将是低效的。散列键没有预测性排序,因此它与数组完全不同。如果这个问题被解决了,那将是一件很遗憾的事情。我认为这是一个很好的问题,它的答案会帮助很多人。可能是@ThisSuiteisBlacknot的重复,它不是链接问题的重复。链接问题询问$x{$i}
是否真的比$x[$i]
快。(不是。)这与泰勒的问题无关。在某些情况下,你应该使用散列的另一个原因是“数组是值的有序列表”。与散列一样。e、 g.$a[2]=“a”$a[0]=“b”$a[1]=“c”;打印值(@a)
不会给出比$h{2}=“a”更多的abc
$h{0}=“b”$h{1}=“c”;打印值(%h)代码>将。这些值只是设置了键,您可以对数组和散列的键进行排序。实际上,区别在于对数组的键进行排序更有效。(在您提到push
和pop
之前,请记住,您可以很容易地使push
和pop
适用于散列。)@ikegami:当然,数组是有序的。您的@a
将始终打印为bca
。它们是按索引排序的。我从来没有说过它们的排序是基于插入的。要么重复我已经说过的(你可以对索引排序),要么你说散列也是按桶索引排序的。(别忘了散列的核心是一个数组。“散列”一词来源于这样一个事实,即该键被散列成一个数字,用作该数组的索引。)是的,散列是有序的,但该顺序对程序员来说是隐藏的,可能会在不通知的情况下更改。从Perl 5.18开始,散列顺序是随机的,并且在同一程序的两次执行之间不会相同。这就是为什么我说散列是有效的
say scalar grep /e/, keys %circles;
861