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

the code is simple below:
use strict; use Data::Dump ('dump'); my $listref = ['a','b','c','d','e']; #### delete @{$listref}[1,3,5]; #### this line is crazy, it should be: delete @{$listref}[0,2,4]; print dump($listref),"\n";
What I want is to delete the array element in 1 3 5, but why I get ('a',undef,'c',undef,'e'), which is opposite?

btw: I hate splice one by one.

Replies are listed 'Best First'.
Re: delete array element from array ref
by GrandFather (Saint) on Aug 22, 2008 at 05:15 UTC

    Perl presents arrays as dynamic but not sparse. As soon as you access element n, all the elements 0 .. n - 1 pop into existence with the value of undef if they didn't exist already. Deleting the contents of elements from the middle of an array doesn't change its length.

    However, under the hood things are a little more complicated. Consider:

    my @array; $array[4] = 0; print " Set element 4: last at $#array\n"; $array[2] = undef; delete $array[4]; print "Delete element 4: last at $#array\n"; delete $array[2]; print "Delete element 2: last at $#array\n";

    Prints:

    Set element 4: last at 4 Delete element 4: last at 2 Delete element 2: last at -1

    so Perl differentiates between array elements that have been assigned to (even if the assignment was undef - that is, the element exists) and unassigned elements (the element doesn't 'exist'). Perl truncates an array back to the last element that exists when element [-1] is deleted. Otherwise, delete simply makes an array element "unassigned" (it doesn't exist any more).

    If you want to remove the elements without leaving holes you could use splice or assign a slice that is the complement of the elements you want to remove:

    use strict; use warnings; use strict; use Data::Dump ('dump'); my $listref = ['a','b','c','d','e']; @$listref = @{$listref}[0, 2, 4]; print "@$listref\n";

    Perl reduces RSI - it saves typing
      Another way to avoid holes would be to filter out the holes with something like

      @{$listref} = grep { defined } @{$listref};

      after performing the deletion. (Of course that assumes that undef isn't a valid value in the list.)

        Better would be:

        @{$listref} = grep {exists} @{$listref};

        Update: this is of course complete bolix as pointed out by tinita++.


        Perl reduces RSI - it saves typing
Re: delete array element from array ref
by Your Mother (Archbishop) on Aug 22, 2008 at 05:17 UTC

    Arrays are indexed from zero. So it's behaving as expected. If you want to delete "a," "c," and "e" they are elements 0, 2, and 4.

    use strict; use warnings; use YAML; my $array = [ "a" .. "e" ]; delete @{$array}[0,2,4]; print Dump $array;

    Hating splice is weird...

Re: delete array element from array ref
by Skeeve (Parson) on Aug 22, 2008 at 04:42 UTC
    perldoc -f splice

    s$$([},&%#}/&/]+}%&{})*;#$&&s&&$^X.($'^"%]=\&(|?*{%
    +.+=%;.#_}\&"^"-+%*).}%:##%}={~=~:.")&e&&s""`$''`"e
    A reply falls below the community's threshold of quality. You may see it by logging in.