Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things

Last index use in array slice

by ltp (Beadle)
on Dec 03, 2012 at 03:27 UTC ( #1006777=perlquestion: print w/replies, xml ) Need Help??
ltp has asked for the wisdom of the Perl Monks concerning the following question:

Greetings Monks,

I know I'm doing something very silly here that has likely been asked and answered countless times before, but my meditation this Monday morning lacks insight.

I'd like to take a slice of an array returned from a method without first assigning the array. Furthermore I'd like the slice to be from an abritrary index to the last index in the array. For example:

my @slice = ( split /\n/, $object->get_array )[$index .. -1];

However, on attempting this I find that the slice contains no values - this makes some sense as there is no overlapping region in the range bounded by the indexes (the region counting forward in the array from index a to the region counting back from the end of the array to index b).(Apologies for the fuzzy language here as I wasn;t sure how to word the terms).

Unfortunately, when I attempt to use $# as the second index for the array slice, I get the warning:

$# is no longer supported at -e line 1.

I do however get a slice containing a single value (the first value of the array). I know I'm clearly overlooking something here, but what? It would be trivial to change this line to first assign the array returned by the split and then use ~~@array as the index of the last value, but this has me trumped.

Replies are listed 'Best First'.
Re: Last index use in array slice
by GrandFather (Sage) on Dec 03, 2012 at 03:33 UTC

    splice does the trick:

    print join ', ', splice @{[split '', '1234567890']}, 5;


    6, 7, 8, 9, 0
    True laziness is hard work

      ...and I am enlightened.

      Thankyou very much for your answer.

Re: Last index use in array slice
by LanX (Chancellor) on Dec 03, 2012 at 03:37 UTC
    First you have to understand that you're slicing a list not an array.

    Then a range from $index .. -1 must be empty because the upper bound must be bigger than the lower one (the range operator has no idea that you mean the biggest index, it's just the number "minus 1")

    When using arrays you can write something like @array[$index..$#array] but as already stated you're not slicing an array and there is nothing like a counter for "last list entry". (your $# is another beast)

    In short, you can't slice a list till the end w/o much obfuscatory magic, so better do it the "normal" way with arrays:

    my @array = split /\n/, $object->get_array; my @slice = @array[$index .. $#array];

    HTH! =)

    Cheers Rolf

Re: Last index use in array slice
by ColonelPanic (Friar) on Dec 03, 2012 at 09:23 UTC

    Another way to do it: instead of splitting everything and then ignoring some of it, find and split only the stuff you want.

    use strict; use warnings; my $str = "discard\ndiscard\nkeep1\nkeep2"; my $discard = 2; my @arr = ($str =~ /^(?:[^\n]*\n){$discard}(.*)/s ? split /\n/, $1 : ( +) ); print "@arr";

    When's the last time you used duct tape on a duct? --Larry Wall
      Alternatively, yet still using the idea of discarding part of the output:
      my(undef, undef, @rest) = split/\n/;
      But, with a variable value for $index, I'd rather go the splice route.

        Yeah, I thought of that one, but ultimately didn't use it because, as you mentioned, it doesn't work well with an arbitrary starting index.

        You could do something like this:

        my $str = "discard\ndiscard\nkeep1\nkeep2"; my $index = 2; my @arr = grep {$index-- <= 0} split "\n", $str;

        When's the last time you used duct tape on a duct? --Larry Wall
Re: Last index use in array slice
by LanX (Chancellor) on Dec 03, 2012 at 12:41 UTC

    (UPDATED code for clarification)

    DB<123> $str =join '', a..h => "abcdefgh" DB<124> ( undef, undef, undef, undef , @rest) = split //, $str => ("a", "b", "c", "d", "e", "f", "g", "h") DB<125> @rest => ("e", "f", "g", "h")

    with arbitrary index, we'll need a dummy array to swallow ignored entries:

    DB<126> $index=4 => 4 DB<127> ( @ignore[1..$index] , @rest) = split //, $str => ("a", "b", "c", "d", "e", "f", "g", "h") DB<128> @rest => ("e", "f", "g", "h")

    cause unfortunately this doesn't work:

    DB<129> ( ( (undef) x $index ) , @rest) = split //, $str Can't modify repeat (x) in list assignment at (eval 65)[multi_perl5db. +pl:638] line 2, at EOF

    Cheers Rolf

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1006777]
Approved by GrandFather
[marto]: someone else writes: [http://www. -im-learning-perl- 6.html|
[marto]: err, Why Iím Learning Perl 6

How do I use this? | Other CB clients
Other Users?
Others perusing the Monastery: (9)
As of 2017-07-26 14:02 GMT
Find Nodes?
    Voting Booth?
    I came, I saw, I ...

    Results (395 votes). Check out past polls.