Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to specify a "tail slice" in Perl?

Tags:

perl

If I want to extract only the 4th, 5th, and 7th elements (say) of tab-separated record, I can do something like:

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

But what if I want the 4th element and the "tail slice" consisting of all elements from the 7th one to the end of the array? I don't know how to do this in a single line. The best I can do is this:

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

The only reason for doing this operation in two lines is so that I can specify $#f in the second line, but this entails a greater degree of specificity than is inherent in the task; the task does not really care how many elements are in the value returned by split. It'd be nice to be able to specify something like "everything available from the 7th element onwards"... This is what I mean by a "tail slice": a slice where only the starting point is specified, while the end point is left implicit.

(This sort of specification is commonplace in uses of the cut utility in Unix; e.g.:

... | cut -f 4,7-

)

Is there some subscripting expression that I can apply directly to the (split(...)) subexpression to produce in one line the same effect as is achieved by the last two lines of code above?

EDIT: To be clear, what I'm trying to avoid is the $#ARRAY construction. I know that I can always do something like

my @f = do { my @t = split(/\t/, $_, -1); @t[3, 6..$#t] };
like image 771
kjo Avatar asked Jan 09 '13 00:01

kjo


Video Answer


1 Answers

The expression in the brackets of a list slice must return a list of zero or more indexes. So you'd have to know the number of items in the list being sliced before it's even produced. So no, it can't be done using a list slice.

The most direct way of accessing a list on the stack is via @_. This does require a sub call, but it does give you an easy mechanism for leaving the list on the stack.

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

Note that this solution does not create an array and copy the values into that array like the code in you've since added to your question.

like image 67
ikegami Avatar answered Oct 03 '22 16:10

ikegami