http://qs321.pair.com?node_id=897663

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

I am getting following error when trying to delete an array element.

"delete argument is not a HASH element or slice at test.pl.."

my $file="test_html"; my @file_lkp=("file1","file2"); for (my $i=0;$i<=$#file_lkp;$i++) { delete $file_lkp[$i] if ($file eq $file_lkp[$i]); }
It is working in Linux but not in Solaris Thanks for your help

Replies are listed 'Best First'.
Re: Perl array delete
by CountZero (Bishop) on Apr 06, 2011 at 06:11 UTC
    If you think it through, deleteing an array element is a somewhat strange concept, except for the highest numbered element.

    Think of an array as an apartment building. You may empty a single floor (set the value of the array-element to zero or the empty string) or even erase all traces of its former occupants (set the value of the aray element to undef), but you cannot take the floor itself away. That would really confuse all tenants living above it! When they arrive home in the evening, they would find their apartment having dropped one level. If you have a fifth floor in your building, you must have all the lower numbered floors (zero to four) as well.

    In other words, as long as there are still array elements with an higher index, you cannot delete the lower numbered ones without fundamentally changing the structure of the array itself.

    PS: Of course functions like pop, push, shift, unshift do change the structure of the array, but only from the top or bottom end.

    CountZero

    A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James

      Thanks for your reply I am confused as it is working in Linux but not in the Solaris...

        Which versions of Perl are you using on those two machines?


        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.
Re: Perl array delete
by wind (Priest) on Apr 06, 2011 at 05:53 UTC

    delete works on is intended for a hash, not an array.

    If you just want to filter out certain elements of an array, use grep or splice:

    my $file = "test_html"; my @file_lkp = ("file1", "file2"); @file_lkp = grep {$_ ne $file} @file_lkp;
      delete works on a hash, not an array.

      Hm. It does 'work' on an array on both 5.8.9 and 5.10.1:

      C:\test>\perl32\bin\perl -Mstrict -we"my @a = 1..10; delete $a[5]; pri +nt qq[@a]" Use of uninitialized value in join or string at -e line 1. 1 2 3 4 5 7 8 9 10 C:\test>\perl64\bin\perl -Mstrict -we"my @a = 1..10; delete $a[5]; pri +nt qq[@a]" Use of uninitialized value in join or string at -e line 1. 1 2 3 4 5 7 8 9 10

      It doesn't really do what you'd hope it would do in as much as it leaves behind an undef in place of the deleted element, but there are no warnings or deprecations.


      Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
      "Science is about questioning the status quo. Questioning authority".
      In the absence of evidence, opinion is indistinguishable from prejudice.
Re: Perl array delete
by GrandFather (Saint) on Apr 06, 2011 at 07:08 UTC

    From the Perl 5.12 perlfunc documentation for delete:

    delete() may also be used on arrays and array slices, but its behavior is less straightforward. Although exists() will return false for deleted entries, deleting array elements never changes indices of existing values; use shift() or splice() for that. However, if all deleted elements fall at the end of an array, the array's size shrinks to the position of the highest element that still tests true for exists(), or to 0 if none do.

    Be aware that calling delete on array values is deprecated and likely to be removed in a future version of Perl.

    Possibly your Solaris system has "a future version of Perl".

    True laziness is hard work
Re: Perl array delete
by hermida (Scribe) on Apr 06, 2011 at 09:24 UTC
    As others have said, delete on an array is not used that often, I can remember only using it once or twice ever for a special situation when I really wanted to leave an undef entry.

    Typically I would say you probably want splice or the other array functions others have mentioned pop, shift because these all and remove array elements and shrink the array and that is a much more often used functionality, at least from my experience.

    Looking at your code you probably want this, no?

    my $file="test_html"; my @file_lkp=("file1","file2"); for (my $i=0;$i<=$#file_lkp;$i++) { splice(@file_lkp, $i, 1) if $file eq $file_lkp[$i]; }