in reply to Re: extracting a list element
in thread extracting a list element

Using delete for arrays is almost always wrong...

I disagree. Deleting an array slice is a very handy operation that I don't regard as useful almost never.

my @a = (2 .. 9); my @i = (2, 3, 5); delete @a[@i]; my @b = grep defined, @a;

Greetings,
-jo

$gryYup$d0ylprbpriprrYpkJl2xyl~rzg??P~5lp2hyl0p$

Replies are listed 'Best First'.
Re^3: extracting a list element ( 'delete @array' explained)
by LanX (Saint) on Jan 06, 2024 at 18:05 UTC
    A much saner way to undefine slices is @a[@i] = () ° ¹

    DB<26> @a = (2 .. 9); DB<27> @i = (2, 3, 5); DB<28> @a[@i] = () DB<29> @b = grep defined, @a; DB<30> x @a 0 2 1 3 2 undef 3 undef 4 6 5 undef 6 8 7 9 DB<31> x @b 0 2 1 3 2 6 3 8 4 9 DB<32> ... DB<65> p exists $a[0] 1 DB<66> p defined $a[0] DB<67>

    Like with hashes is delete not assigning undef but kicking the element's value out of existence.

    Now the size of hashes is shrinking by the number of deleted elements. But with arrays this only happens for elements at the end of the array, which is shortened then. While this is consistent with the use of exists , it might lead to unpredictable behavior.*

    This explains the stark warning.

    DB<40> @a = (0..4) DB<41> delete @a[0,2,4] DB<42> p exists $a[0] DB<43> p exists $a[1] 1 DB<44> x @a # shortened 0 undef 1 1 2 undef 3 3 DB<45> p scalar @a 4 DB<46>

    Bottom line: only use delete with arrays if you really want to differentiate between defined and exists and this shrinking behavior is anticipated.

    In order to remove array elements use splice. If you need sparse arrays, consider using hashes with numbers as keys. *

    Cheers Rolf
    (addicted to the Perl Programming Language :)
    see Wikisyntax for the Monastery

    footnotes

    °) unfortunately is undef @arr[@slice] not DWIM.

    *) Paragraph rephrased

    ¹) and @b = grep exists, @a; is the way to go together with delete. This way you won't get caught by accidental undef values.

    update

    To better highlight that undef is an existing value but non existence is translated to undef after assignment:

    DB<56> x @a 0 undef 1 1 2 undef 3 3 DB<57> $a[5] = undef DB<58> x @a 0 undef 1 1 2 undef 3 3 4 undef. # gap 5 undef. # value DB<59> p exists $a[4] DB<60> p exists $a[5] 1 DB<61>

Re^3: extracting a list element
by LanX (Saint) on Jan 06, 2024 at 14:00 UTC
    From delete

    WARNING: Calling delete on array values is strongly discouraged. The notion of deleting or checking the existence of Perl array elements is not conceptually coherent, and can lead to surprising behavior.

    Cheers Rolf
    (addicted to the Perl Programming Language :)
    see Wikisyntax for the Monastery