Hashes

delete#

Remove the named key-value pair(s) from a hash, or element(s) from an array, and return what was removed.

delete reaches into an aggregate and removes the specified entries outright — not just by setting them to undef. After delete, exists on the same key or index returns false, keys no longer lists it, and iterating the hash with each skips it. The argument must be an element or slice of a hash or array; its final operation selects what to remove, and anything leading up to that operation (dereferences, method calls) is just navigation.

Synopsis#

delete $hash{KEY}           # scalar key
delete @hash{LIST}          # hash slice: values of the listed keys
delete %hash{LIST}          # key/value hash slice (5.20+)
delete $array[INDEX]        # array element
delete @array[LIST]         # array slice

What you get back#

In list context, delete returns the value or values removed, in argument order. A slice argument whose key or index did not exist yields undef at the matching position, so the length of the returned list matches the length of the key/index list.

In scalar context, delete returns the value of the last element removed, or undef if the key/index was not present.

The 5.20+ key/value hash-slice form delete %hash{LIST} returns a list of alternating key/value pairs — two elements for every deleted entry — which makes it the idiomatic way to pluck a named set of entries and keep both sides.

my %h = (foo => 11, bar => 22, baz => 33);
my $v = delete $h{foo};            # 11
my @v = delete @h{qw(bar quux)};   # (22, undef)
my %kv = delete %h{qw(baz quux)};  # (baz => 33, quux => undef)

Global state it touches#

  • %ENVdelete $ENV{VAR} unsets the environment variable for the current process and its future children. The effect is real, not just the Perl-side hash; system calls see the change.

  • tied aggregatesdelete dispatches to the DELETE method of the tying package. The return value is whatever the implementation chooses to hand back; some tied hashes return the deleted value, some do not.

  • $_ — unaffected. delete does not default to anything; EXPR is mandatory.

Examples#

Remove one key, inspect what was there:

my %cfg = (host => "db1", port => 5432, user => "alice");
my $old_host = delete $cfg{host};
# $old_host is "db1"; exists $cfg{host} is false

Free memory by removing many entries in one call (hash slice):

delete @cache{@stale_keys};

Pluck a set of named entries and keep the pairs (5.20+ kv-slice):

my %h = (a => 1, b => 2, c => 3);
my %taken = delete %h{qw(a c)};
# %taken is (a => 1, c => 3); %h is (b => 2)

Delete through a nested structure. Leading navigation can be arbitrary — only the final operation decides what gets removed:

my $tree = { users => { alice => { roles => [qw(admin ro)] } } };
delete $tree->{users}{alice}{roles}[0];
# roles is now (undef, "ro")
delete $tree->{users}{alice};
# the whole user record is gone

Avoid autovivification on the read side while still removing on the write side. delete never vivifies the intermediate hashes it walks through:

delete $h{outer}{inner};    # does not create $h{outer} if absent

Compare with splice when you want indices to renumber. delete on an array element leaves a hole; splice closes the hole:

my @a = (10, 20, 30, 40);
delete $a[1];
# @a is (10, undef, 30, 40); $#a is still 3

my @b = (10, 20, 30, 40);
splice(@b, 1, 1);
# @b is (10, 30, 40); $#b is 2

Edge cases#

  • delete vs assigning undef: $h{k} = undef leaves k in the hash with an undefined value; exists $h{k} is still true. delete $h{k} removes the key entirely.

  • Missing key in scalar context: delete $h{nope} returns undef. That’s indistinguishable from deleting a key whose value was undef; use exists first if the distinction matters.

  • each + delete inside the loop: safe when you delete only the current key (the key just returned by each). Deleting other keys during iteration can skip entries or revisit them — Perl’s hash iterator is not stable across structural change. The safe rewrite is to collect keys first:

    for my $k (grep { $h{$_} < 0 } keys %h) {
        delete $h{$k};
    }
    
  • Trailing array deletions shrink the array: if the deleted elements are at the top end, $#array drops to the highest index still testing true under exists. Holes in the middle stay as holes.

  • delete on an array is discouraged: the concept of “missing index” is not coherent for arrays — indices are positional, not named. Leave array shrinkage to shift, pop, or splice. WARNING in upstream POD restated: reach for an array delete only when you know you want a hole.

  • delete local $h{k}: removes the entry for the enclosing block and reinstates it on scope exit. Useful for temporarily hiding configuration keys from code called inside the block without losing the original value:

    {
        local $ENV{LANG};         # still present, but undef
        delete local $ENV{PATH};  # gone for this block only
        run_thing();
    }   # both restored to original values here
    
  • Tied hash, tied array: delete calls DELETE; the return value is whatever the tie implementation supplies. A tied DBM hash deletes the entry on disk.

  • Readonly target: delete on a readonly element croaks with Modification of a read-only value attempted.

  • The expression must end in an element or slice: delete $h{k} + 1 is a compile-time error; delete has lower precedence than arithmetic and expects an lvalue-ish aggregate lookup, not a computed value.

Differences from upstream#

Fully compatible with upstream Perl 5.42.

See also#

  • exists — the query counterpart; use it before delete when you need to tell “was never there” apart from “was there with value undef

  • each — hash iterator; safe to combine with delete only when you delete the current key

  • keys — snapshot of hash keys; the usual way to build a deletion list that won’t interact with iterator state

  • values — companion to keys when you want the deleted-value set without the keys

  • splice — the right tool when you want to remove array elements and renumber remaining indices

  • undef — clears a whole aggregate (undef %h, undef @a) or a single scalar; the customary way to empty a hash or array wholesale rather than deleting every key