Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Can someone explain a purpose anyone would need to use this? I just came across this in The Perl Black Book 2 and I just don't see a reason for this. You could use delete $array[] and assign a new value $array[] = .... And can someone explaing offset and length? I don't quite understand what those are/do.

Replies are listed 'Best First'.
Re: array splicing
by BrowserUk (Patriarch) on Jan 29, 2004 at 23:21 UTC

    Maybe this will explain it?

    @a = qw[1 2 3 4 5]; print "@a"; 1 2 3 4 5 splice @a, 1,3, qw[1.5 2 2.5 3 3.5 4 4.5]; print "@a"; 1 1.5 2 2.5 3 3.5 4 4.5 5

    The splice line above say's: replace elements @a[1,2,3] (offset 1, length 3) with the list that follows.

    Using delete and assignment (or just assignment) you can replace 1 for 1 in the array. Whereas, using splice you can replace any number (length) of elements at any offset, with any number of replacement elements. More or less than the number being replaced.


    Examine what is said, not who speaks.
    "Efficiency is intelligent laziness." -David Dunham
    "Think for yourself!" - Abigail
    Timing (and a little luck) are everything!

Re: array splicing
by Stevie-O (Friar) on Jan 29, 2004 at 23:27 UTC
    Think of splicing as 'cut and paste' for arrays.
    @foo = splice @bar, offset, length, LIST
    This does the following:
    1. Starting with $bar[offset], 'cuts' length elements from @bar.
    2. 'Pastes' the LIST (this may do nothing if LIST is empty) into @bar at that very point.
    3. Returns the items 'cut' in step 1 (and assigning them to @foo)
    I looked at http://perldoc.com/perl5.8.0/pod/func/splice.html, and I admit that it's in need of short, simple examples, so here are some:
    @bar = 0..9; @foo = splice(@bar, 3, 2); # $bar[3] and $bar[4] are removed. # now @foo is (3, 4) and @bar is (0,1,2,5,6,7,8,9) @bar = 0..9; splice(@bar, 5, 0, 100, 200); # Note that the 'length' is zero. This means *nothing* is removed from + @bar. # then, 100 and 200 are pasted in so # @bar is (0,1,2,3,4,100,200,5,6,7,8,9) @bar = 0..10; @foo = splice(@bar, 7, 3, 300); # $bar[7], $bar[8], and $bar[9] are removed, and returned # to @foo. the value '300' is inserted there. # now @bar = (0,1,2,3,4,5,6,300,10) # and @foo = (7,8,9)
    Hope this helps!
    --Stevie-O
    $"=$,,$_=q>|\p4<6 8p<M/_|<('=> .q>.<4-KI<l|2$<6%s!<qn#F<>;$, .=pack'N*',"@{[unpack'C*',$_] }"for split/</;$_=$,,y[A-Z a-z] {}cd;print lc
Re: array splicing
by Ao (Friar) on Jan 29, 2004 at 23:29 UTC
    If you only want to keep the first three elements of an array, you'd use splice(@array, 3); or as an alternative to using pop(@array); you could use splice(@array, -1); since a negative offset means to start that many places from the end of the array. You have to remember that there is always more than one way to do anything with perl.

    Length refers to the number of positions to splice, so to remove the fifth and sixth postitions from an array, use splice(@array, 4, 2);

    If this isn't as clear as mud, take a longer look at Programming Perl or Perl in a Nutshell.

Re: array splicing
by ysth (Canon) on Jan 30, 2004 at 01:53 UTC
    I often use splice to grab more than one item out of a list at a time. E.g. instead of:
    for my $x (@list) { do something with $x }
    you can do
    while (my ($x,$y) = splice(@list, 0, 2)) { do something with $x and $y }
    Of course, the latter destroys the list as it iterates over it.

    Did you have specific questions about offset and length that aren't answered in the fine manual?

    With the above while loop, changing to splice(@list, -2) will grab $x and $y off the end of the array instead of the beginning (though that way will die if @list has an odd number of elements instead of just getting an undef $y).

    May I suggest a super search of splice to see many different ways of using it?

    Update: said slice where meant splice.

Re: array splicing
by David Caughell (Monk) on Jan 30, 2004 at 05:19 UTC

    Firstly, a slice is just a set of elements of an array. In other words, if you want the first 5 and last 5 members of a class of 100 people, you would write:

    my @smalllist = @biglist[0 .. 4, 95 .. 99];

    Note that while using a slice you access an array as a list (@) rather than a scalar($).

    Using a slice keeps the @biglist the same as when you started. If you want to trim off the @biglist to eliminate the people in the @smalllist from it, you could use a splice() function call to do it.

    my @smalllist = splice(@biglist,0,5), splice(@biglist,-5,5);

    Mostly, the reason that you would use splice() is just because it's a quick way of getting rid of the elements of a list as you use them, especially when you're using them in a unusual order or in sizes other than 1.

    The Offset means where you start your splice from, and either refers to a position away from the start of the list (if you use a positive number) or away from the end of the list (if you use a negative number).

    Length is how many elements you're going to cut away from the list.

    Hope this helps,
    Dave.

    P.S.
    When I was first learning Perl, I was very excited about how flexible the functions were, and I read quite a bit of the perlfunc document. You might want to try that. Afterwards, though, I read Programming Perl (which I still don't fully understand). It's a challenging read, but worth it. If you only read up on the functions, you won't see the full power of the language.

    You can read about the functions here: http://www.perldoc.com/perl5.8.0/pod/perlfunc.html