Perl学习笔记5——高级Perl技巧:切片、grep与map初步

列表切片

在一个列表中,特别是由函数返回的列表中,有时往往只需要取出其中的某几个元素使用。比较一般的办法是将此列表存入一个数组中,然后通过索引值来取出数组元素。但这样的做法会引入一个新的数组,且除了取用的元素以外,其他的元素都没有用处,从而造成了资源上的浪费。

Perl可以将一个列表直接当作一个数组使用,可以使用下标表达式来取出其中的一个或多个元素,这样的操作就称为列表切片。由于列表可以直接被当作数组使用,这样就避免了引入新数组的浪费。例:

$_=(1..10)[1];    #把(1..10)当作一个数组,后接下标[1]表示取用索引值为1的列表元素,并赋值给变量

在使用列表切片时,必须要在函数返回的列表的外层加上一对小括号,构造出列表上下文中的一个列表。例:

$_=(reverse 1..10)[1];    #在reverse返回的列表的外层加上一对括号,构造出列表上下文,然后再对此列表使用列表切片

切片不仅能只切出一个元素,其也可以一次性切出多个元素,并返回一个列表。如果要一次切出多个列表元素,将方括号内的单个下标数字换为由多个下标数字组成的列表即可,这个列表的小括号可以省略。数字之间顺序不限,并且可以重复。例:

($n,$m)=(1..10)[1,-1];            #切出列表中索引值为1的元素和最后一个元素,并将切出的列表赋值给变量列表

@n=(reverse 1..10)[1,1,1,1,1];     #切出5个列表中索引值为1的元素,并将切出的列表赋值给@n

注意:列表切片同列表一样,不能进行双引号内插。

数组切片

下标表达式可以用来取出数组中的一个元素,这是一种常用的可以访问单个数组元素的做法。而类似于列表切片,在数组中也可以一次性切出多个数组元素,并返回一个列表。这样的操作就称为数组切片。数组切片是另一种访问数组元素的做法,其可以一次性访问多个数组元素。

Perl中,$符号一般指取用单个元素,而@符号不仅可以表示整个数组,其也可以与$相对,表示取用多个元素,@是下标表达式的第二种标识符。所以如果下标表达式使用@开头,就表示取用多个数组元素,即数组切片。而相对应的,其下标数字也应由一个数字变为由多个索引值构成的列表。数组切片的返回值也是一个列表,下标数字顺序不限,且可以重复,这些都与列表切片一致。例:

$n[1]      #使用$作为下标表达式的标识符,取出数组中的一个元素

@n[1..5]   #使用@作为下标表达式的标识符,取出数组中的多个元素

数组切片返回的是一个列表,所以可以应用在各种需要列表的环境中。例:

($n,$m)=@n[2,4];     #将数组切片返回的列表赋值给变量列表

for(@n[1..5]){print}    #将数组切片返回的列表作为foreach的参数

数组切片同数组一样,也可以进行双引号内插,且内插的各个数组元素之间会自动以空格隔开,这是其与列表切片的一大不同之处。例:

print"@n[1..5]";    #数组切片内插

哈希切片

哈希切片与数组切片十分相似。其使用@而不是$作为标识符,表示取用多个元素,哈希切片会返回哈希值列表。在哈希切片的下标表达式中,原先花括号围住的单个哈希键应换成由多个哈希键构成的键列表。例:

$hash{a}            #取出单个哈希值

@hash{qw/a b c/}    #取出qw/a b c/这个哈希键列表对应的多个哈希值,即哈希切片

通过哈希切片切出的哈希值列表可以运用于各种列表上下文中。例:

@hash{qw/a b c/}=qw/aaa bbb ccc/;    #使用哈希切片同时对这三个哈希键进行赋值

同数组切片,哈希切片也可以进行双引号内插。例:

print"@hash{qw/a b c/}";    #哈希切片内插

下标表达式的特征性符号

通过上文可知,下标表达式不仅可以用来取用单个数组元素或哈希元素,其也可以用来进行上文所述的三类切片操作。而下标表达式在进行这两种不同的操作时,其返回值所处的上下文是不同的。当取用单个元素时,下标表达式返回的是一个标量,此时其上下文就是标量上下文,而进行切片操作时,下标表达式返回的是一个列表,此时其上下文则是列表上下文。而这其中的决定性因素就在于下标表达式的标识符,这是下标表达式的一类特征性符号。

下标表达式的标识符有两种:$和@,这两种符号决定了下标表达式的上下文。$符号表示取单个元素,所以当以$作为标识符时,下标表达式就是标量上下文,而@符号表示取多个元素,即切片,所以当以@作为标识符时,其上下文就是列表上下文。例:

$n[1]     #由$决定标量上下文

@n[1,2]   #由@决定列表上下文

列表切片是一种特殊的下标表达式,其恒为列表上下文,也就是说,即使列表切片切出的元素只有一个,此时也是列表上下文。例:

(1..5)[1]   #列表切片中的下标表达式,此时为列表上下文

除了$与@,在下标表达式中还有另一类特征性符号,即方括号与花括号,这一对符号决定了下标表达式的操作对象。方括号与花括号均出现于下标表达式的下标中,用于包裹下标数字或哈希键。显然,如果下标表达式使用的是一对方括号,那么其操作对象就是一个数组或列表,而如果下标表达式使用的是一对花括号,那么其操作对象就是哈希。例:

$n[1]              #由“[ ]”决定了下标表达式的操作对象是数组

@hash{qw/a b c/}    #由“{ }”决定了下标表达式的操作对象是哈希

grep操作符初步

grep与下文中的map操作符都是Perl中的两个非常重要的列表操作符。grep操作符可以用来筛选一个列表中的特定元素,在列表上下文中,其可以将满足条件的所有元素作为一个列表返回,而在标量上下文中,其可以返回筛选出的列表中的元素个数,即满足条件的元素个数。

grep操作符的参数分为两部分,第一部分为一个返回布尔值的代码块,又称选择器。第二部分为需要进行筛选的数组或列表。在grep运行过程中,类似于foreach循环,$_会依次成为列表中每一个元素的临时别名,然后在代码块中对$_进行运算并得到一个布尔值,如果此布尔值为真,那么这个元素就会被筛选出来。全部筛选完毕后,grep会将所有筛选出的元素以一个列表返回。

注意,由于$_是列表元素的临时别名,所以不建议在grep的代码块中对$_的值进行修改,因为这将直接修改列表中元素的值。例:

print grep{$_>5}1..10;    #$_会依次成为(1..10)中每一个元素的临时别名,并判断$_>5是否为真,如果为真则筛出。grep在列表上下文中最终返回所有符合条件的元素构成的列表

$n=grep{$_>5}1..10;     #在标量上下文中返回满足条件的元素的个数

grep还有更简便的一种写法,如果代码块中的运算式简短到只有一行(如上例),就可以直接将这个运算式作为grep的第一参数书写,从而省去代码块结构,而grep的操作对象则作为其第二参数。例:

print grep$_>1,0,1,2,3;    #直接将代码块改为grep的第一参数书写,第二参数为一个省略括号的列表,即grep进行筛选的列表

map操作符初步

map操作符可以用于修改列表中每一个元素的值。其工作方式和书写规则均与grep十分相似。$_会依次成为列表中每一个元素的临时别名,然后执行含有$_的代码块,从而对$_进行修改,并最终返回整个修改过的列表。

map操作符的参数同grep一样,由代码块和需要处理的数组或列表组成。且如果代码块简短到只有一行,就可以直接将代码块改写为map的第一参数。例:

print map$_+=1,1..10;    #以$_分别作为列表中每一个元素的临时别名,并返回$_+=1的结果,最终输出由每一个结果所组成的列表

任何形式的grep和map语句都可以改写为foreach循环语句,但由于foreach语句每次只能返回一个元素的判断或运算结果,所以当处理整个数组或列表时,就一定需要一个临时数组来存放结果,这就造成了资源上的浪费。而grep和map可以一次性进行每个元素的运算,直接返回最终的结果列表,从而省去了创建临时数组来存放结果的麻烦,使运算更为高效,也使代码更为简洁。


樱雨楼

完成于2016.1.8

最后修改于2016.1.29

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,362评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,330评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,247评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,560评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,580评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,569评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,929评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,587评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,840评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,596评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,678评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,366评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,945评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,929评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,165评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,271评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,403评论 2 342

推荐阅读更多精彩内容

  • 第六章:数字 第七章:序列,列表,元组 1.序列 序列类型有着相同的访问模式:它的每一个元素可以通过指定一个偏移量...
    m风满楼阅读 871评论 0 2
  • 这是16年5月份编辑的一份比较杂乱适合自己观看的学习记录文档,今天18年5月份再次想写文章,发现简书还为我保存起的...
    Jenaral阅读 2,727评论 2 9
  • 列表和数组的概念与性质 列表是Perl中的第二种数据结构,是一组标量的有序集合。数组是存储列表的容器,是一种可以存...
    樱雨楼阅读 1,017评论 0 0
  • 哈希的概念与性质 哈希是Perl中的第三种数据结构,又称关联数组。其与数组具有一定的相似性,许多特性可以与数组形成...
    樱雨楼阅读 1,272评论 0 0
  • 最近心里承受能力差了点 看到脏东西心里产生巨大颤抖 起鸡毛的那种 好慌 简直想跳起来 随时脱口而出一句 MD 要...
    5mh_阅读 154评论 0 0