6

如果我只想提取制表符分隔记录的第 4、第 5 和第 7 个元素(例如),我可以执行以下操作:

my @f = (split(/\t/, $_, -1))[3, 4, 6];

但是,如果我想要第 4 个元素和包含从第 7 个元素到数组末尾的所有元素的“尾部切片”怎么办?我不知道如何在一行中做到这一点。我能做的最好的是:

my @f = split(/\t/, $_, -1);
@f = @f[3, 6..$#f];

在两行中执行此操作的唯一原因是我可以$#f在第二行中指定,但这需要比任务固有的更大程度的特异性;该任务并不真正关心返回的值中有多少元素split。能够指定诸如“从第 7 个元素开始的所有可用内容”之类的东西会很好......这就是我所说的“尾部切片”的意思:只指定起点的切片,而结束点是隐含的。

(这种规范cut在 Unix 中使用该实用程序时很常见;例如:

... | cut -f 4,7-

)

是否有一些下标表达式可以直接应用于(split(...))子表达式以在一行中产生与上面最后两行代码相同的效果?

编辑:要清楚,我要避免的是$#ARRAY建筑。我知道我总是可以做类似的事情

my @f = do { my @t = split(/\t/, $_, -1); @t[3, 6..$#t] };
4

1 回答 1

8

列表切片括号中的表达式必须返回零个或多个索引的列表。因此,您甚至必须在生成列表之前就知道列表中被切片的项目数。所以不,它不能使用列表切片来完成。

访问堆栈上列表的最直接方法是 via @_。这确实需要一个子调用,但它确实为您提供了一种将列表留在堆栈上的简单机制。

my @f = sub { @_[6..$#_] }->( split(/\t/, $_, -1) );

请注意,此解决方案不会创建数组并将值复制到该数组中,就像您添加到问题中的代码一样。

于 2013-01-09T01:03:59.580 回答