Array函数

原地(In-place)array修改函数

我们用@stack来演示这些函数:

  1. my @stack = ("Fred", "Eileen", "Denise", "Charlie");
  2. print @stack; # "FredEileenDeniseCharlie"

[pop](http://perldoc.perl.org/functions/pop.html)抽取并返回array的最后一个元素,可以认为是栈顶的元素:

  1. print pop @stack; # "Charlie"
  2. print @stack; # "FredEileenDenise"

[push](http://perldoc.perl.org/functions/push.html)向array末尾添加一个元素:

  1. push @stack, "Bob", "Alice";
  2. print @stack; # "FredEileenDeniseBobAlice"

[shift](http://perldoc.perl.org/functions/shift.html)抽取并返回array的第一个元素:

  1. print shift @stack; # "Fred"
  2. print @stack; # "EileenDeniseBobAlice"

[unshift](http://perldoc.perl.org/functions/unshift.html)向array的头部插入一个元素:

  1. unshift @stack, "Hank", "Grace";
  2. print @stack; # "HankGraceEileenDeniseBobAlice"

poppushshiftunshift都是[splice](http://perldoc.perl.org/functions/splice.html)的特例。splice返回删除的一个array的切片,并且用另一个array的切片在原array中替换之:

  1. print splice(@stack, 1, 4, "<<<", ">>>"); # "GraceEileenDeniseBob"
  2. print @stack; # "Hank<<<>>>Alice"

从现有的array创建新的array

Perl提供下面这些函数,可以操作现有的array产生新的array。

[join](http://perldoc.perl.org/functions/join.html)函数把多个字符串连接成一个字符串:

  1. my @elements = ("Antimony", "Arsenic", "Aluminum", "Selenium");
  2. print @elements; # "AntimonyArsenicAluminumSelenium"
  3. print "@elements"; # "Antimony Arsenic Aluminum Selenium"
  4. print join(", ", @elements); # "Antimony, Arsenic, Aluminum, Selenium"

在列表上下文,[reverse](http://perldoc.perl.org/functions/reverse.html)函数把传入的列表逆序返回,在scalar上下文,reverse先把字符串列表连接起来,再将这个字符串反转。

  1. print reverse("Hello", "World"); # "WorldHello"
  2. print reverse("HelloWorld"); # "HelloWorld"
  3. print scalar reverse("HelloWorld"); # "dlroWolleH"
  4. print scalar reverse("Hello", "World"); # "dlroWolleH"

[map](http://perldoc.perl.org/functions/map.html)函数接受一个array,并将一个操作应用于这个array中的每一个scalar $_,然后返回用这些scalar创建的array。这个操作用在花括号中的一个表达式来表示:

  1. my @capitals = ("Baton Rouge", "Indianapolis", "Columbus", "Montgomery", "Helena", "Denver", "Boise");
  2. print join ", ", map { uc $_ } @capitals;
  3. # "BATON ROUGE, INDIANAPOLIS, COLUMBUS, MONTGOMERY, HELENA, DENVER, BOISE"

[grep](http://perldoc.perl.org/functions/grep.html)函数接受一个array,并返回一个经过筛选的array。语法与map类似,而第二个参数会对array中的每个scalar $_求值,如果返回true,这个scalar就会被放到输出array中,否则就不会。

  1. print join ", ", grep { length $_ == 6 } @capitals;
  2. # "Helena, Denver"

显然,返回的array长度是满足条件的元素个数,这就意味着你可以用grep检查array中是否包含某个元素:

  1. print scalar grep { $_ eq "Columbus" } @capitals; # "1"

grepmap的组合形成了list comprehensions这种许多其他语言中欠缺的非常强大特性。(译者注:list comprehensions大致的意思是利用map和filter从现有的列表构造新的列表,表达的含义是对一个列表中满足某个条件的所有元素上应用某个操作,而形成一个新的列表。)

默认情况下,[sort](http://perldoc.perl.org/functions/sort.html)函数对输入的array按字母序进行排序:

  1. my @elevations = (19, 1, 2, 100, 3, 98, 100, 1056);
  2. print join ", ", sort @elevations;
  3. # "1, 100, 100, 1056, 19, 2, 3, 98"

然而,与grepmap类似,排序总是通过一系列元素的两两比较来进行的。你的代码块接受$a$b作为输入,如果$a“小于”$b则返回-1,如果“相等”则返回0,而如果$a“大于”$b则返回1。

cmp运算符适用于字符串(译者注:按字母序比较):

  1. print join ", ", sort { $a cmp $b } @elevations;
  2. # "1, 100, 100, 1056, 19, 2, 3, 98"

这个“宇宙飞船运算符”<=>适用于数值:

  1. print join ", ", sort { $a <=> $b } @elevations;
  2. # "1, 2, 3, 19, 98, 100, 100, 1056"

$a$b总是scalar,但是它们也许是某个复杂对象的引用,那样就很难直接进行比较。如果你需要更多篇幅来描述这种比较,你可以单独创建一个子程序来描述它,并在用到它的地方提供这个子程序的名字:

  1. sub comparator {
  2. # lots of code...
  3. # return -1, 0 or 1
  4. }
  5. print join ", ", sort comparator @elevations;

不过你不能对grepmap这样做。

请注意,我们从来没有显式提供$a$b给子程序和语句块。就像$_一样,$a$b实际上是当一对值需要比较时被填入的全局变量。