locked_user rumos-er has asked for the wisdom of the Perl Monks concerning the following question:

Hi, ALL.

As I know Perl 5.6.6 and greater supports use of function "delete" with arrays. I'm work with 5.8.8.

As I understand next code must be completed in 5 itterations.

#!/usr/bin/perl -w use strict; my $array=[5,4,3,2,1]; srand(time()); my $cnt=0; while(scalar(@{$array}) ) { my $index=int(rand(scalar(@{$array}))); delete($array->[$index]); warn $index." ".scalar(@{$array}); $cnt++; sleep(1); }; warn $cnt;

I make this test (after long hours of searching for a bug in module) with 'v5.8.8 built for i386-freebsd-64int' and with 'v5.8.8 built for MSWin32-x86-multi-thread (ActiveState)'. Every time I get different value of $cnt. Where is my error or mistake ?)

Thnx for your attention,
Alex.

Replies are listed 'Best First'.
Re: using function delete with arrays
by cdarke (Prior) on Jul 17, 2007 at 11:24 UTC
    You will get a different value for $cnt because you are actually extending the array each time.
    From Perl 5.6.0, delete may be used on an array element. It sets the element to its undefined state, but does not shift the index of the ones after them - use splice for that. As with a hash, delete returns the deleted value.
    This does not buy you much over using undef, in fact undef can be more efficient, but delete can be used on an array slice, which undef cannot.
    The function exists can also be used on an array element, but not on a slice. The result given by exists is subtle. If the element was delete'd then both defined and exists will return FALSE. If the element was set to undef, then defined returns FALSE but exists returns TRUE!
      1. I know about slice. Thnx.
      2. So where is a bug or logical humor of function delete ?
      2.1. When all elements of array are 'deleted' then array is realy clear.
      2.2. Also if I make delete of last(!) element(-s) of array - number of array items will changes (I calculate it as result of scalar function not as $#).
      As I understand - scalar or delete works wrong. Exactly what of them - is my main question :)

        2.1, 2.2: The first paragraph of "perldoc -f delete" contains:

        In the case of an array, if the array elements happen to be at the end, the size of the array will shrink to the highest element that tests true for exists() (or 0 if no such element exists).

        Does this reasonably answer your question?

Re: using function delete with arrays
by moritz (Cardinal) on Jul 17, 2007 at 11:22 UTC
    The number of elements only decreases, when the last element is delete()ed:

    $ perl -wle 'my $a=[2,3,4]; delete($a->[1]); print scalar @$a' 3 $ perl -wle 'my $a=[2,3,4]; delete($a->[1]); print scalar @$a' 3 $ perl -wle 'my $a=[2,3,4]; delete($a->[2]); print scalar @$a' 2
Re: using function delete with arrays
by locked_user rumos-er (Novice) on Jul 17, 2007 at 11:16 UTC
    As I understand (after taking attention under first warn) - when all array items marked(my first mistake that if I assign every array element to undef and then call scalar(@array) then I've must to get 0 been wrong. Because of that I say "marked" as deleted) as deleted it's realy clear array.. So my new question - where can I get true about "delete" and arrays :).

    Thnx for your attention,
    Alex.
      Another idea how to accomplish what you (presumably) want to do:

      use List::Util qw(shuffle); @list = shuffle @list; # now you can just shift() or pop() until @list is empty
      Your understanding is incorrect. scalar(@array) returns the number of elements in an array. Whether the element is defined or not doesn't matter:
      $ perl -e '@arr = (1, 2, 3); print scalar(@arr), "\n"' 3 $ perl -e '@arr = (undef, undef, undef); print scalar(@arr), "\n"' 3