Perl散列基础:创建、更新、循环、删除和排序

散列是Perl的核心数据类型之一。本文描述了在Perl中处理散列的主要函数和语法规则。

声明和初始化

散列是一个无序的键值对集合。在散列中,键是一个唯一的字符串,它引用特定的值。初始化后,散列可以被修改。因为散列是无序的,如果需要以特定顺序输出其内容,则必须在输出时进行排序。Perl使用“%”符号作为散列的变量符号。此命令将声明一个空散列

my %hash;

类似于数组的语法,散列也可以使用逗号分隔的值列表进行声明

my %weekly_temperature = ('monday', 65, 'tuesday', 68, 'wednesday', 71, 'thursday', 53, 'friday', 60);

在上面的代码中,Perl将列表中的第一个条目作为键(“monday”),将第二个条目作为该键的值(65)。列表中的第三个条目(“tuesday”)然后被声明为键,第四个条目(68)作为其值,依此类推。

“肥逗号”运算符看起来像一个箭头(“=>”),允许声明键值对,而不是使用逗号。这使得代码更简洁、更易读。此外,使用肥逗号时,不需要对键的字符串进行引号。使用肥逗号,对%weekly_temperature的相同声明将如下所示

my %weekly_temperature = (
    monday    => 65, 
    tuesday   => 68,
    wednesday => 71, 
    thursday  => 53, 
    friday    => 60,
);

访问一个值

要访问键值对的值,Perl需要将键放在花括号内。

my %weekly_temperature = (
    monday    => 65, 
    tuesday   => 68,
    wednesday => 71, 
    thursday  => 53, 
    friday    => 60,
);
my $monday_temp = $weekly_temperature{monday};
#65

请注意,当键的字符串放在散列键的花括号内时,不需要引号;当访问单个标量值时,使用标量符号(“$”)而不是(“%”)。

从散列中获取切片

切片是一系列值。在Perl中,切片可以读入数组、分配给单个标量,或作为函数或子例程的输入。当只想从散列中提取少量值时,切片非常有用。例如

my %weekly_temperature = (
    monday    => 65,
    tuesday   => 68,
    wednesday => 71,
    thursday  => 53,
    friday    => 60,
);

my ($tuesday_temp, $friday_temp) = @weekly_temperature{('tuesday', 'friday')};

print "$tuesday_temp\n";
#68

print "$friday_temp\n";
#60

上面的代码通常声明了‘weekly_temperature’散列。这里不同寻常的是,为了获取值的切片,使用数组符号(“@”)将散列变量名称前缀,这样散列将查找值的列表。

使用values函数访问所有值

values函数返回散列中包含的值的列表。可以遍历返回的值列表并对其执行操作(例如打印)。例如

my %weekly_temperature = (
    monday    => 65, 
    tuesday   => 68,
    wednesday => 71, 
    thursday  => 53, 
    friday    => 60,
);
foreach my $value (values %weekly_temperature){
    print $value . "\n";
}
#71 
#53 
#60
#65 
#68

在处理散列的键值对时的一些建议:如果垂直对齐肥逗号(“=>”)运算符,则代码更易读;与C不同,Perl允许最后一个元素有尾随逗号,这使得在以后添加元素时更容易而不会生成编译错误。

使用keys函数访问所有键

keys函数返回散列中包含的键的列表。访问散列中所有键值对的一种常见方法是通过遍历keys函数返回的列表。例如

my %consultant_salaries = (
    associate        => 25000,
    senior_associate => 40000,
    manager          => 80000,
    director         => 120000,
    partner          => 250000,
);
foreach my $grade (keys %consultant_salaries) {
    print "$grade: $consultant_salaries{$grade}\n";
}
#associate: 25000
#partner: 250000
#director: 120000
#manager: 80000
#senior_associate: 40000

在上面的代码中,我们使用keys函数返回一个键列表,使用foreach遍历列表,然后打印每个对的键和值。请注意,对的打印顺序与初始顺序不同——这是因为散列以随机内部顺序存储它们的对。我们还使用了解释引号字符串(“”)。这允许我们混合变量和纯文本以及转义字符,如换行符(’\n’),以便于打印。

使用each函数访问所有键值对

each函数逐个返回散列的所有键和值

my %consultant_salaries = (
    associate        => 25000,
    senior_associate => 40000,
    manager          => 80000,
    director         => 120000,
    partner          => 250000,
);
while (my ($key, $value) = each %consultant_salaries) {
    print "$key: $value\n";
}
#associate: 25000
#partner: 250000
#director: 120000
#manager: 80000
#senior_associate: 40000

添加新的键值对

要将新的一对添加到哈希中,请使用以下语法

# declare the hash as usual
my %fruit_pairs = (apples => 'oranges');

# add a new key value pair
$fruit_pairs{oranges} = 'lemons';

# prove the new pair exists by printing the hash
while (my ($key, $value) = each %fruit_pairs) {
    print "$key: $value\n";
}
#apples: oranges
#oranges: lemons

删除键值对

要从哈希中删除键值对,请使用delete函数。删除需要键值对的键来从哈希中删除它

my %fruit_pairs = (apples => 'oranges');

# use the delete function with the pair's key
delete $fruit_pairs{apples};

更新一对的值

要更新一对的值,只需使用与添加新的键值对相同的语法分配新值。这里的区别是键已经在哈希中存在

my %fruit_pairs = (apples => 'oranges');
# assign a new value to the pair
$fruit_pairs{apples} = 'bananas';

清空哈希

要清空哈希,重新声明它,不包含任何成员

my %fruit_pairs = (apples => 'oranges');

# empty the hash
%fruit_pairs = ();

增加/减少一个值

快速回答:使用与使用增量或减量运算符分配/更新值相同的语法

my %common_word_count = (
    the => 54,
    and => 98,
    a   => 29,
);

# increment the value of the pair with the key 'the' by 1
$common_word_count{the}++;

# decrement the key value pair with the key 'a'
$common_word_count{a}--;

按字母顺序排序哈希

尽管哈希的内部顺序是随机的,但可以将哈希的输出排序成更有用的顺序。Perl提供了sort函数来(显然)排序数据列表。默认情况下,它按字母顺序排序

my %common_word_count = (
    the => 54,
    and => 98,
    a   => 29,
);
# use sort with keys to sort the keys of a hash
foreach my $key (sort keys %common_word_count){
   print "$key\n";
}
#a
#and
#the

# to sort values use keys to lookup the values and a compare block to compare them
foreach my $key (sort {$common_word_count{$a} cmp $common_word_count{$b}} keys %common_word_count){
       print "$key: $common_word_count{$key}\n";
}
#a: 29
#the: 54
#and: 98

让我们回顾上面的代码。比较块使用keys函数接收哈希键。然后它使用特殊变量$a和$b比较每个键的值。然后将这个排序后的键列表传递给foreach命令并按常规遍历。注意打印的顺序是按值顺序的 - 然而,它仍然是字母顺序。

按数字排序哈希

按数字排序哈希需要使用与上一个示例中的比较块相同的比较块,但将‘cmp’运算符替换为数字比较运算符(’<=>’)

my %common_word_count = (
            the => 54,
            and => 98,
            a   => 29,
);

foreach my $key (sort {$common_word_count{$a} <=> $common_word_count{$b}} keys %common_word_count) {
    print "$key: $common_word_count{$key}\n";
}

获取哈希大小

要获取哈希的大小,只需在标量上下文中调用keys函数。这可以通过将keys的返回值赋给标量变量来完成

my %common_word_count = (
            the => 54,
            and => 98,
            a   => 29,
);

my $count =  keys %common_word_count;
print "$count\n";
#3


本文最初发布在PerlTricks.com上。

标签

David Farrell

David是一位专业程序员,他经常在Twitter博客上关于代码和编程艺术发表推文。

浏览他们的文章

反馈

这篇文章有问题吗?请在GitHub上打开问题或拉取请求以帮助我们。