ZetCode

Perl 数组

最后修改于 2023 年 8 月 24 日

Perl 数组教程展示了如何在 Perl 中使用数组。

数组是值的有序列表。数组的元素可以通过它们的索引访问;索引从零开始。

数组是 Perl 的一种基本数据类型。数据类型是一组值以及可以对这些值进行的操作。

在 Perl 中,数组和列表这两个词经常可以互换使用。有时,程序员将数组一词用于变量(@vals),而将列表一词用于数组定义右侧的数据字面量,例如:(1, 2, 3, 4, 5)

Perl 使用 @ 符号来定义数组变量。

my @words = ('sky', 'cup', 'forest', 'war', 'cloud');

我们有一个字符串数组。

$ cpanm Array::Compare

在本教程中,我们将使用几个外部模块。这些模块可以使用 cpanm 工具安装。

Perl 简单数组

在下面的示例中,我们处理一个简单的数组。

simple.pl
#!/usr/bin/perl

use 5.30.0;
use warnings;

my @vals = (1, 2, 3, 4, 5, 6);

say $vals[0];
say $vals[1];
say $vals[-1];

$vals[6] = 7;
$vals[7] = 8;

$, = ' ';
say @vals;

my $n = @vals;

say "\@vals has $n elements"; 

在示例中,我们处理一个整数数组。

my @vals = (1, 2, 3, 4, 5, 6);

我们定义一个整数值数组。变量名前面有 @ 符号。数组的元素包含在一对 ()括号内,并由逗号分隔。

say $vals[0];
say $vals[1];
say $vals[-1];

我们通过索引访问数组的元素;第一个索引是 0。最后一个元素可以使用索引 -1 访问。索引放在 [] 括号内。由于我们访问的是单个元素,因此我们在变量名中使用 $ 符号。

$vals[6] = 7;
$vals[7] = 8;

我们在数组中添加两个新值。

$, = ' ';
say @vals;

我们打印 @vals 数组的内容;为了更清晰地输出,我们将输出字段分隔符设置为空格。

my $n = @vals;

当我们在标量上下文中 quartic 使用数组时,我们得到数组的元素数量。这也可以通过 scalar 函数来完成。

$ ./simple.pl 
1
2
6
1 2 3 4 5 6 7 8
@vals has 8 elements

Perl 访问数组元素

在下一个示例中,我们访问数组元素。

accessing.pl
#!/usr/bin/perl

use 5.30.0;
use warnings;

my @vals = (11, 12, 13, 14, 15, 16);

say $vals[0];
say $vals[1];
say $vals[-1];
say $vals[-2];

say '-----------------------';

say scalar @vals;
say $#vals;

say '-----------------------';

say $vals[$#vals];

数组元素通过其索引访问。第一个索引的值为 0。最后一个索引是 $#vals。可以使用负索引从末尾访问数组元素。

say $vals[0];
say $vals[1];
say $vals[-1];
say $vals[-2];

我们打印四个元素的数值。第一个值的索引是 0,第二个是 1。最后一个索引是 -1,倒数第二个是 -2。索引放在 [] 字符内,变量名前面有 $ 符号。

say scalar @vals;
say $#vals;

我们使用 scalar 函数打印元素数量,并使用 $#vals 打印最后一个索引值。

$ ./accessing.pl 
11
12
16
15
-----------------------
6
5
-----------------------
16

Perl 列表赋值

我们可以一次性将一系列值赋给多个变量。

assign.pl
#!/usr/bin/perl

use 5.30.0;
use warnings;

my ($a, $b, $c) = (1, 2, 3);

say "$a $b $c";

变量在左侧,列表字面量在右侧。

Perl 命令行参数

Perl 将命令行参数存储在特殊变量 @ARGV 中。

cmd_argv.pl
#!/usr/bin/perl

use 5.30.0;
use warnings;
use Data::Dumper qw(Dumper);

die "Usage: $0 arg1 arg2 arg3\n" if @ARGV < 3;

say $ARGV[0];
say $ARGV[2];

say Dumper \@ARGV;

在示例中,我们打印两个参数,然后使用 Dumper 打印整个数组。

die "Usage: $0 arg1 arg2 arg3\n" if @ARGV < 3;

如果参数少于三个,我们将以用法输出结束脚本。$0 变量引用程序名称。在此表达式(if @ARGV < 3)中,数组在标量上下文中 quartic 使用,我们将数组中的元素数量与值 3 进行比较。

$ ./cmd_argv.pl 1 2 3
1
3
$VAR1 = [
          '1',
          '2',
          '3'
        ];

Perl 子例程参数

Perl 将传递给子例程的参数存储在特殊变量 @_ 中。

sub_args.pl
#!/usr/bin/perl

use 5.30.0;
use warnings;

my $r = add3(1, 2, 3);
say $r;

sub add3 {

    my ($a, $b, $c) = @_;

    return $a + $b + $c;
}

在示例中,我们在 add3 子例程中添加三个值。我们利用 @_ 数组来获取参数。

$ ./sub_args.pl 
6

Perl 数组是值类型

将一个数组赋给另一个数组会创建它的副本。在某些语言中, such an assignment would create a reference to the original array.

value_type.pl
#!/usr/bin/perl

use 5.30.0;
use warnings;

my @vals = (1, 2, 3, 4, 5, 6);
my @vals2 = @vals;

$vals[0] = 11;
$vals[1] = 22;

say "@vals";
say "@vals2";

我们将一个数组赋给另一个数组并更改其两个值。新数组的值不受影响。

$ ./value_type.pl 
11 22 3 4 5 6
1 2 3 4 5 6

Perl 数组范围运算符

范围 .. 运算符允许我们简化包含形成序列的值的数组的创建。

range_operator.pl
#!/usr/bin/perl

use 5.30.0;
use warnings;

my @vals = (1 .. 11);
my @chars = ('a' .. 'z');

my $n1 = @vals;
my $n2 = @chars;

say "\@vals has $n1 elements";
say "\@chars has $n2 elements";

$, = ' ';
say @vals;
say @chars;

我们使用 .. 运算符创建整数和字符数组。

$ ./range_operator.pl 
@vals has 11 elements
@chars has 26 elements
1 2 3 4 5 6 7 8 9 10 11
a b c d e f g h i j k l m n o p q r s t u v w x y z

Perl 数组切片

切片是数组的一部分。切片可以使用 .. 范围运算符或 , 逗号运算符创建。

slices.pl
#!/usr/bin/perl

use 5.30.0;
use warnings;

my @vals = (1 .. 10);

$, = ' ';

say @vals[1, 2, -1];

say '--------------------';

my @sl1 = @vals[1..4];
my @sl2 = @vals[1, 2, 4, 5];
my @sl3 = @vals[5..$#vals];
my @sl4 = @vals[2..$#vals-3];

say @sl1;
say @sl2;
say @sl3;
say @sl4;

我们从整数数组中创建几个切片。

say @vals[1, 2, -1];

此切片包含索引为 1、2 和 -1 的元素。

my @sl1 = @vals[1..4];

此切片包含索引从 1 到 4 的元素。

my @sl3 = @vals[5..$#vals];

此切片包含从 5 到最后一个元素的元素。

$ ./slices.pl 
2 3 10
--------------------
2 3 4 5
2 3 5 6
6 7 8 9 10
3 4 5 6 7

Perl 数组包含元素

在下面的示例中,我们检查数组是否包含指定的元素。

contains.pl
#!/usr/bin/perl

use 5.30.0;
use warnings;
use experimental 'smartmatch';

my @words = ('forest', 'novice', 'war', 'sky', 'colour', 'tool', 
    'smart', 'wooden', 'cup', 'cloud');

my $val = shift || 'cup';

if ($val ~~ @words) {

    say "$val is in the array";
} else {

    say "$val is not in the array";
}

我们使用实验性的 ~~“智能匹配”运算符。

use experimental 'smartmatch';

这行关闭了警告。

$ ./contains.pl 
cup is in the array
$ ./contains.pl forest
forest is in the array
$ ./contains.pl chair
chair is not in the array

Perl qw 函数

Perl 包含一个方便的 qw 函数,它简化了字符串值数组的书写。

quote_word.pl
#!/usr/bin/perl

use 5.30.0;
use warnings;
use Data::Dumper qw/Dumper/;

my @words = qw/forest novice war sky colour tool smart wooden cup cloud/;

say $words[-1];
say $words[-2];
say Dumper \@words;

使用 qw 函数,我们不必写引号字符和逗号。

use Data::Dumper qw/Dumper/;

Data::Dumper 模块对于调试很有用;我们可以快速查看数据结构的 contents。

my @words = qw/forest novice war sky colour tool smart wooden cup cloud/;

我们使用 qw 创建一个单词列表。

$ ./quote_word.pl 
cloud
cup
$VAR1 = [
          'forest',
          'novice',
          'war',
          'sky',
          'colour',
          'tool',
          'smart',
          'wooden',
          'cup',
          'cloud'
          ];

Perl 数组 push 和 pop

push 函数将一个值列表附加到数组的末尾。pop 函数删除并返回数组的最后一个元素。

pushing.pl
#!/usr/bin/perl

use 5.30.0;
use warnings;

my @vals = (1 .. 5);

push @vals, 6;
push @vals, 7, 8, 9;

say "@vals";

my $r = pop @vals;
say "$r";

say "@vals";

在示例中,我们使用 push 向数组附加值,并使用 pop 从数组末尾删除值。

my @vals = (1 .. 5);

我们有一个整数数组。

push @vals, 6;

我们将值 6 附加到数组的末尾。

push @vals, 7, 8, 9;

在这里,我们将三个值附加到数组的末尾。

my $r = pop @vals;
say "$r";

使用 pop,我们删除数组的最后一个元素并将其打印到控制台。

$ ./pushing.pl 
1 2 3 4 5 6 7 8 9
9
1 2 3 4 5 6 7 8

Perl 数组 shift 和 unshift

unshift 函数将给定的元素列表附加到数组的开头,而 shift 则删除并返回数组的第一个元素。

shifting.pl
#!/usr/bin/perl

use 5.30.0;
use warnings;

my @vals = (1 .. 5);

unshift @vals, 0;
unshift @vals, -3, -2, -1;

say "@vals";

my $r = shift @vals;
say $r;

say "@vals";

在示例中,我们使用 unshiftshift 函数在数组开头添加和删除值。

$ ./shifting.pl 
-3 -2 -1 0 1 2 3 4 5
-3
-2 -1 0 1 2 3 4 5

Perl 数组展平

在 Perl 中,数组在组合时会被展平。

flattening.pl
#!/usr/bin/perl

use 5.30.0;
use warnings;

my @vals1 = (1 .. 5);
my @vals2 = (6 .. 10);
my @vals = (@vals1, @vals2);

say "@vals";

foreach my $val ((1, 2, 3), (4, 5, 6)) {

    say $val;
}

当我们组合 @vals1@vals2 时,我们形成一个数组,该数组在一层中包含两个数组的所有元素。

$ ./flattening.pl 
1 2 3 4 5 6 7 8 9 10
1
2
3
4
5
6

Perl 数组嵌套

要创建嵌套数组的数组,我们将数组的引用放在父数组中。数组的引用使用 [] 方括号创建。

array_of_arrays.pl
#!/usr/bin/perl

use 5.30.0;
use warnings;

my @vals = ([1, 2], [3, 4], [5, 6]);

say "@{$vals[0]}";
say "@{$vals[1]}";
say "@{$vals[2]}";

say '---------------------';

say $vals[0][0];
say $vals[0][1];
say $vals[2][0];
say $vals[2][1];

在示例中,我们创建了一个二维整数数组。

say "@{$vals[0]}";

使用一个索引,我们得到一个嵌套数组的引用。要取消引用它,我们使用 @{} 字符。

say $vals[0][0];

要获取元素,我们在两个 [] 方括号对中使用两个索引。

$ ./array_of_arrays.pl 
1 2
3 4
5 6
---------------------
1
2
5
6

Perl 数组求和、最小值、最大值、乘积

在下一个示例中,我们计算整数数组的某些统计信息。

funs.pl
#!/usr/bin/perl

use 5.30.0;
use warnings;
use List::Util qw/sum0 min max product/;

my @vals = (1, 2, 3, 4, 5, 6);

say 'The sum is: ' . sum0 @vals;
say 'The maximum is: ' . max @vals;
say 'The minimum is: ' . min @vals;
say 'The product is: ' . product @vals;

sum0minmaxproduct 函数是从 List::Util 模块导入的。

say 'The sum is: ' . sum0 @vals;

sum0 返回 @vals 中所有元素的数值和。当给出空列表时,它返回 0。

$ ./funs.pl 
The sum is: 21
The maximum is: 6
The minimum is: 1
The product is: 720

Perl 数组 map 函数

map 函数将一个表达式应用于数组的每个元素,并返回一个包含更新结果的新数组。

map_fun.pl
#!/usr/bin/perl

use 5.30.0;
use warnings;

my @vals = (1 .. 8);
my @r = map { $_ * 2} @vals;

say "@r";

my @words = qw/SKY blue Tree sun cup wood/;
my @r2 = map { lc $_ } @words;

say "@r2";

我们在两个数组上使用 map 函数。

my @vals = (1 .. 8);
my @r = map { $_ * 2} @vals;

这里我们将数组的每个元素乘以 2。$_ 是一个特殊变量,代表当前值。

my @words = qw/SKY blue Tree sun cup wood/;
my @r2 = map { lc $_ } @words;

我们有一个单词列表。我们将 lc(小写)函数应用于每个单词。

$ ./map_fun.pl 
2 4 6 8 10 12 14 16
sky blue tree sun cup wood

Perl 数组经典 for 循环

在 Perl 中,我们可以使用由 C 语言普及的经典 for 循环来遍历数组的元素。

classic_for.pl
#!/usr/bin/perl

use 5.30.0;
use warnings;

my @vals = (1 .. 10);
my $n = @vals;

$\ = ' ';

for (my $i = 0; $i < $n; $i++) {

    print $vals[$i];
}

$\ = '';
print "\n";

我们有一个整数列表。使用经典 for 循环,我们遍历数组并打印所有元素。

my @vals = (1 .. 10);
my $n = @vals;

在 for 循环中,我们需要知道数组的大小。

for (my $i = 0; $i < $n; $i++) {

    print $vals[$i];
}

在循环中,我们有一个辅助变量 $i,它用作计数器。for 循环有三个阶段:初始化、条件和代码块执行以及增量。

$ ./classic_for.pl 
1 2 3 4 5 6 7 8 9 10 

Perl 数组 while 循环

我们可以使用 while 循环遍历数组。

while_loop.pl
#!/usr/bin/perl

use 5.30.0;
use warnings;

my @vals = (1 .. 8);
my $n = @vals;

$\ = ' ';

my $i = 0;

while ($i < $n) {

    print $vals[$i];
    $i++;
}

$\ = '';
print "\n";

在这种情况下,我们还需要确定数组的大小并使用辅助变量 $i

Perl 数组 foreach 循环

在 foreach 循环中,我们为数组的每个元素运行一个代码块。

foreach_loop.pl
#!/usr/bin/perl

use 5.30.0;
use warnings;

my @vals = (1 .. 10);

$\ = ' ';

foreach my $val (@vals) {

    print $val;
} 

say "\n------------------------";

foreach (@vals) {

    print $_;
} 

$\ = '';
print "\n";

我们使用 foreach 循环遍历整数数组的元素。

foreach my $val (@vals) {

    print $val;
} 

在每次迭代中,当前值存储在临时变量 $val 中。

foreach (@vals) {

    print $_;
} 

如果我们省略辅助变量,当前值将存储在特殊变量 $_ 中。

$ ./foreach_loop.pl 
1 2 3 4 5 6 7 8 9 10 
------------------------
1 2 3 4 5 6 7 8 9 10 

如果省略临时变量,for 循环就是 foreach 的同义词。

for_foreach.pl
#!/usr/bin/perl

use 5.30.0;
use warnings;

my @vals = (1 .. 10);

$\ = ' ';

foreach (@vals) {

    print $_;
}

say "\n--------------------------";


for (@vals) {

    print $_;
}

$\ = '';
print "\n";

在此示例中,foreachfor 循环是相同的。

Perl 数组控制迭代

可以使用 nextlast 关键字控制迭代。

controlling_iteration.pl
#!/usr/bin/perl

use 5.30.0;
use warnings;

my @vals = (1, 2, -3, -4, 5, 6, 7, 8, 9);

foreach (@vals) {

    next if $_ < 0;
    say $_;
}

say '------------------------------';

foreach (@vals) {

    last if $_ < 0;
    say $_;
}

next 语句在循环中使用以开始下一次迭代并跳过其下方的所有代码,而 last 语句用于立即退出循环。

foreach (@vals) {

    next if $_ < 0;
    say $_;
}

在此循环中,我们跳过所有负值。next 语句会跳过小于 0 的值的 say 语句,但会继续进行下一次迭代。

foreach (@vals) {

    last if $_ < 0;
    say $_;
}

在此循环中,我们打印所有正值,直到遇到第一个负值。如果我们遇到负整数,我们将使用 last 语句终止循环。

$ ./controlling_iteration.pl 
1
2
5
6
7
8
9
------------------------------
1
2

Perl 数组 splice

使用 splice 函数,我们可以删除或替换数组的元素。

splicing.pl
#!/usr/bin/perl

use 5.30.0;
use warnings;

my @words = qw/sky blue tree sun cup wood/;

say "original data: @words";

say '------------------------';

my @removed = splice @words, 2, 1;

say "removed word: @removed";
say "@words";

say '------------------------';

my @updated = splice @words, 2, 1, 'sunset';

say "updated word: @updated";
say "@words";

我们有一个单词数组。我们使用 splice 函数删除一个单词并替换一个单词。

my @removed = splice @words, 2, 1;

第三个元素被移除。被移除的元素被返回。splice 的第二个参数是偏移量,第三个是长度。(我们从第三个位置移除一个元素。)

my @updated = splice @words, 2, 1, 'sunset';

我们用单词 'sunset' 替换第三个元素。

$ ./splicing.pl 
original data: sky blue tree sun cup wood
------------------------
removed word: tree
sky blue sun cup wood
------------------------
updated word: sun
sky blue sunset cup wood

Perl 数组唯一值

List::MoreUtils 包含用于处理数组的有用函数。

unique.pl
#!/usr/bin/perl

use 5.30.0;
use warnings;
use List::MoreUtils qw/uniq duplicates/;
use Data::Dumper qw(Dumper);

my @vals = (1, 1, 1, 2, 2, 3, 4, 5, 5, 6);

say "original array: @vals";

my @uniq_vals = uniq @vals;
say "unique values: @uniq_vals";

my @dup_vals = duplicates @vals;
say "values having duplicates: @dup_vals";

uniq 函数通过去除重复值返回一个新列表。duplicates 函数返回一个包含列表中重复值的新列表。

$ ./unique.pl 
original array: 1 1 1 2 2 3 4 5 5 6
unique values: 1 2 3 4 5 6
values having duplicates: 1 2 5

Perl 数组 split/join

split 函数可用于将字符串分割成子字符串数组。join 函数可用于将值列表组合成字符串。

split_join.pl
#!/usr/bin/perl

use 5.30.0;
use warnings;
use Data::Dumper qw(Dumper);

my $text = 'There is an old hawk in the sky';
my @words = split ' ', $text;

say Dumper(\@words);

my $output = join ' ', @words;
say $output;

示例使用 splitjoin 函数。

my $text = 'There is an old hawk in the sky';
my @words = split ' ', $text;

我们将句子分割成单词数组。句子以空格字符为分隔。

my $output = join ' ', @words;

使用 join,我们可以执行相反的操作。我们将数组的单词连接成一个字符串。

$ ./split_join.pl 
$VAR1 = [
          'There',
          'is',
          'an',
          'old',
          'hawk',
          'in',
          'the',
          'sky'
        ];

There is an old hawk in the sky

Perl 数组查找元素

firstval 函数返回列表中使块求值为 true 的第一个元素。lastval 函数返回列表中使块求值为 true 的最后一个值。这些函数是 List::MoreUtils 模块的一部分。

finding.pl
#!/usr/bin/perl

use 5.30.0;
use warnings;
use List::MoreUtils qw/firstval lastval/;

my @words = ('forest', 'novice', 'war', 'sky', 'colour', 'tool', 'smart', 
    'wooden', 'cup', 'cloud');

say firstval { $_ =~ /^[Ww]/ } @words;
say lastval { $_ =~ /^[Ww]/ } @words;

say '----------------------';

say firstval { length $_ == 3 } @words;
say lastval { length $_ == 3 } @words;

say '----------------------';

say firstval { $_ =~ /(\w)(\1+)/ } @words;
say lastval { $_ =~ /(\w)(\1+)/ } @words;

在示例中,我们在单词列表中搜索特定项。

say firstval { $_ =~ /^[Ww]/ } @words;
say lastval { $_ =~ /^[Ww]/ } @words;

我们搜索以字母 'w' 开头的第一个/最后一个字符串。我们使用正则表达式。

say firstval { length $_ == 3 } @words;
say lastval { length $_ == 3 } @words;

我们搜索第一个/最后一个正好有三个字符的字符串。我们使用 length 函数获取当前单词的大小。

say firstval { $_ =~ /(\w)(\1+)/ } @words;
say lastval { $_ =~ /(\w)(\1+)/ } @words;

我们搜索第一个/最后一个包含重复字符(如 oo 或 ee)的字符串。再次,我们使用正则表达式。

$ ./finding.pl 
war
wooden
----------------------
war
cup
----------------------
tool
wooden

Perl 比较数组

Array::Compare 是一个用于在 Perl 中比较数组的模块。

comparing.pl
#!/usr/bin/perl

use 5.30.0;
use warnings;
use Array::Compare;

my @vals1 = (1, 2, 3, 4, 5);
my @vals2 = (1, 2, 3, 4, 5);

my $c = Array::Compare->new;
 
if ($c->compare(\@vals1, \@vals2)) {

  say "\@vals1 and \@vals2 are equal";
} else {

  say "\@vals1 and \@vals2 are not equal";
}

my @words1 = qw/sky blue cup/;
my @words2 = qw/blue sky cup/;
my @words3 = qw/sky blue cup/;

if ($c->compare(\@words1, \@words2)) {

  say "\@words1 and \@words2 are equal";
} else {

  say "\@words1 and \@words2 are not equal";
}

if ($c->compare(\@words1, \@words3)) {

  say "\@words1 and \@words3 are equal";
} else {

  say "\@words1 and \@words3 are not equal";
}

在示例中,我们比较整数和字符串数组。

my $c = Array::Compare->new;

创建了一个新的比较器对象。

if ($c->compare(\@words1, \@words2)) {

我们将两个数组的引用传递给 compare 函数。

$ ./comparing.pl 
@vals1 and @vals2 are equal
@words1 and @words2 are not equal
@words1 and @words3 are equal

单词的顺序很重要;因此,@words1@words2 不相等。

比较器对象可以接受可选参数。Case 选项决定比较是否区分大小写。如果我们不提供该选项,则默认进行区分大小写的比较。

comparing2.pl
#!/usr/bin/perl

use 5.30.0;
use warnings;
use Array::Compare;

my $c1 = Array::Compare->new(Case => 1);

my @words1 = qw/sky blue cup borrow sun moon/;
my @words2 = qw/sky blue cup borrow Sun Moon/;

if ($c1->compare(\@words1, \@words2)) {

  say "\@words1 and \@words2 are equal";
} else {

  say "\@words1 and \@words2 are not equal";
}

my $c2 = Array::Compare->new(Case => 0);

if ($c2->compare(\@words1, \@words2)) {

  say "\@words1 and \@words2 are equal";
} else {

  say "\@words1 and \@words2 are not equal";
}

在示例中,我们对两个单词数组进行区分大小写和不区分大小写的比较。

$ ./comparing2.pl 
@words1 and @words2 are not equal
@words1 and @words2 are equal

Perl 排序数组

sort 函数返回列表的排序元素。原始值保持不变。默认情况下,数字按数值排序,字符串按字典序排序。

sorting.pl
#!/usr/bin/perl

use 5.30.0;
use warnings;

my @vals = (1, 2, 3, 4, 5, 6);
my @words = qw/war sky cup atom blue stone near/;

$, = ' ';
say sort @vals;
say sort @words;

say '-----------------';

say sort { $b <=> $a } @vals;
say sort { $b cmp $a } @words;

在示例中,我们对整数列表和字符串列表进行排序。

say sort @vals;
say sort @words;

没有块结构,数字和字符串按升序自然排序。

say sort { $b <=> $a } @vals;

块返回有关排序方式的信息。$a$b 是特殊的全局变量,它们保存列表中的两个值以进行排序。三向比较运算符 <=> 用于比较数字。要按降序比较数字,我们交换 $a$b 变量。

say sort { $b cmp $a } @words;

字符串使用 cmp 函数进行比较。

$ ./sorting.pl 
1 2 3 4 5 6
atom blue cup near sky stone war
-----------------
6 5 4 3 2 1
war stone sky near cup blue atom

在下一个示例中,我们展示了如何按长度对字符串进行排序。

sorting2.pl
#!/usr/bin/perl

use 5.30.0;
use warnings;

my @words = qw/war sky bibliotheque cup atom blue as clear 
    bibiotheque stone near atomic animal/;

$, = ' ';

say sort @words;
say sort { $b cmp $a } @words;

say '-----------------';

say sort { length($a) <=> length($b) } @words;
say sort { length($b) <=> length($a) } @words;

我们有一个单词列表。我们先按字典序排序列表,然后按单词长度排序。

say sort { length($a) <=> length($b) } @words;
say sort { length($b) <=> length($a) } @words;

我们在块结构中使用 length 函数比较这两个值。因为 length 函数返回大小作为整数,所以我们使用三向比较运算符。

$ ./sorting2.pl 
animal as atom atomic bibiotheque bibliotheque blue clear cup near sky stone war
war stone sky near cup clear blue bibliotheque bibiotheque atomic atom as animal
-----------------
as war sky cup atom blue near clear stone atomic animal bibiotheque bibliotheque
bibliotheque bibiotheque atomic animal clear stone atom blue near war sky cup as

在下一个示例中,我们对嵌套列表的列表进行排序。

sorting3.pl
#!/usr/bin/perl

use 5.30.0;
use warnings;

my @users = (['John Doe', 'gardener', 1250], ['Jane Doe', 'teacher', 980], 
    ['Lucy Smith', 'accountant', 1100], ['Robert Roe', 'driver', 1020]);

my @s1 = sort { $a->[1] cmp $b->[1]} @users;

foreach (@s1) {

    say join ', ', @{$_};
}

say '----------------------';

my @s2 = sort { $b->[2] <=> $a->[2]} @users;

foreach (@s2) {

    say join ', ', @{$_};
}

在示例中,我们按职业和薪水对用户进行排序。

my @users = (['John Doe', 'gardener', 1250], ['Jane Doe', 'teacher', 980], 
     ['Lucy Smith', 'accountant', 1100], ['Robert Roe', 'driver', 1020]);

每个嵌套列表代表一个用户。

my @s1 = sort { $a->[1] cmp $b->[1]} @users;

在这里,我们按职业对用户进行排序。

my @s2 = sort { $b->[2] <=> $a->[2]} @users;

在这里,我们按薪水对用户进行排序。

$ ./sorting3.pl 
Lucy Smith, accountant, 1100
Robert Roe, driver, 1020
John Doe, gardener, 1250
Jane Doe, teacher, 980
----------------------
John Doe, gardener, 1250
Lucy Smith, accountant, 1100
Robert Roe, driver, 1020
Jane Doe, teacher, 980

Perl 数组过滤

grep 函数根据给定表达式过滤数组。

filtering.pl
#!/usr/bin/perl

use 5.30.0;
use warnings;

my @vals = (-1, 0, 2, 1, 5, -6, -2, 3, 4);

my @r1 = grep {$_ > 0} @vals;
say "@r1";

my @r2 = grep {$_ < 0} @vals;
say "@r2"; 

my @r3 = grep {$_ % 2 == 0} @vals;
say "@r3"; 

在示例中,我们过滤了一个整数值列表。

my @r1 = grep {$_ > 0} @vals;

此行提取正整数。

my @r2 = grep {$_ < 0} @vals;

在这里,我们获取所有负数。

my @r3 = grep {$_ % 2 == 0} @vals;

在此行中,我们获取所有偶数。

$ ./filtering.pl 
2 1 5 3 4
-1 -6 -2
0 2 -6 -2 4

在下一个示例中,我们使用正则表达式进行过滤。

filtering2.pl
#!/usr/bin/perl

use 5.30.0;
use warnings;

my @data = ('sky', 'new', 3, 'tool', 7, 'forest', 'cup', 'cloud', 5);

my @r1 = grep /\d/, @data;
say "@r1";

my @r2 = grep !/\d/, @data;
say "@r2";

我们定义了一个包含整数和单词的数组。我们首先过滤出所有整数,然后过滤出所有单词。

$ ./filtering2.pl 
3 7 5
sky new tool forest cup cloud

我们进一步使用正则表达式。

filtering3.pl
#!/usr/bin/perl

use 5.30.0;
use warnings;

my @words = qw/sky new tool bar forest cup cloud tennis ball wood pen coffee/;

my @r1 = grep /^...$/, @words;
say "@r1"; 

my @r2 = grep /(\w)(\1+)/, @words;
say "@r2"; 

首先,我们提取所有三个字母的单词,然后提取所有带有重复字符的单词。

$ ./filtering3.pl 
sky new bar cup pen
tool tennis ball wood coffee

File::Find::Rule 是一个用于遍历目录的模块。

filtering4.pl
#!/usr/bin/perl

use 5.30.0;
use warnings;
use File::Find::Rule;

$, = ' ';

my @files = File::Find::Rule->name("*.pl")->in("..");
my @found = grep { -M $_ > 180 } @files;

say join "\n", @found;

在示例中,我们查找所有比 180 天旧的 Perl 文件。File::Find::Rule 返回找到的文件数组。

在本文中,我们学习了如何在 Perl 中使用数组。

作者

我的名字是 Jan Bodnar,我是一名充满激情的程序员,拥有丰富的编程经验。我从 2007 年开始撰写编程文章。迄今为止,我已撰写了 1,400 多篇文章和 8 本电子书。我在编程教学方面有十多年的经验。

列出 所有 Perl 教程