View Full Version : delete from array referenced by hash

03-16-2006, 04:04 PM
Im trying to delete a array element from a array reference by a hash. Pushing onto the array works but the delete wont.

sub add{

# Get fields user selected to add
@fields = param("available_fields");

# Add fields to my_data session variable, remove from data session variable
foreach $field(@fields){
push (@{$my_data{$table_selected}},$field);
delete $data{$prev_table}[$field];

03-16-2006, 05:24 PM
The delete command is used to remove an element from a hash not an array. To remove an array element you need to use shift, pop, or splice. shift removes the first element, pop removes the last element, and splice removes 1 or more elements from anywhere in the array.

perldoc -f pop
pop Pops and returns the last value of the array, shortening the
array by one element. Has an effect similar to


If there are no elements in the array, returns the undefined
value (although this may happen at other times as well). If
ARRAY is omitted, pops the @ARGV array in the main program, and
the @_ array in subroutines, just like "shift".

perldoc -f shift
shift ARRAY
shift Shifts the first value of the array off and returns it,
shortening the array by 1 and moving everything down. If there
are no elements in the array, returns the undefined value. If
ARRAY is omitted, shifts the @_ array within the lexical scope
of subroutines and formats, and the @ARGV array at file scopes
or within the lexical scopes established by the "eval ''",
"BEGIN {}", "INIT {}", "CHECK {}", and "END {}" constructs.

See also "unshift", "push", and "pop". "shift" and "unshift" do
the same thing to the left end of an array that "pop" and "push"
do to the right end.

perldoc -f splice
splice ARRAY
Removes the elements designated by OFFSET and LENGTH from an
array, and replaces them with the elements of LIST, if any. In
list context, returns the elements removed from the array. In
scalar context, returns the last element removed, or "undef" if
no elements are removed. The array grows or shrinks as
necessary. If OFFSET is negative then it starts that far from
the end of the array. If LENGTH is omitted, removes everything
from OFFSET onward. If LENGTH is negative, removes the elements
from OFFSET onward except for -LENGTH elements at the end of the
array. If both OFFSET and LENGTH are omitted, removes
everything. If OFFSET is past the end of the array, perl issues
a warning, and splices at the end of the array.

The following equivalences hold (assuming "$[ == 0 and $#a >=
$i" )

push(@a,$x,$y) splice(@a,@a,0,$x,$y)
pop(@a) splice(@a,-1)
shift(@a) splice(@a,0,1)
unshift(@a,$x,$y) splice(@a,0,0,$x,$y)
$a[$i] = $y splice(@a,$i,1,$y)

Example, assuming array lengths are passed before arrays:

sub aeq { # compare two list values
my(@a) = splice(@_,0,shift);
my(@b) = splice(@_,0,shift);
return 0 unless @a == @b; # same len?
while (@a) {
return 0 if pop(@a) ne pop(@b);
return 1;
if (&aeq($len,@foo[1..$len],0+@bar,@bar)) { ... }

perldoc -f delete
delete EXPR
Given an expression that specifies a hash element, array
element, hash slice, or array slice, deletes the specified
element(s) from the hash or array. 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).

Returns a list with the same number of elements as the number of
elements for which deletion was attempted. Each element of that
list consists of either the value of the element deleted, or the
undefined value. In scalar context, this means that you get the
value of the last element deleted (or the undefined value if
that element did not exist).

%hash = (foo => 11, bar => 22, baz => 33);
$scalar = delete $hash{foo}; # $scalar is 11
$scalar = delete @hash{qw(foo bar)}; # $scalar is 22
@array = delete @hash{qw(foo bar baz)}; # @array is (undef,undef,33)

Deleting from %ENV modifies the environment. Deleting from a
hash tied to a DBM file deletes the entry from the DBM file.
Deleting from a "tie"d hash or array may not necessarily return

Deleting an array element effectively returns that position of
the array to its initial, uninitialized state. Subsequently
testing for the same element with exists() will return false.
Note that deleting array elements in the middle of an array will
not shift the index of the ones after them down--use splice()
for that. See "exists".

The following (inefficiently) deletes all the values of %HASH
and @ARRAY:

foreach $key (keys %HASH) {
delete $HASH{$key};

foreach $index (0 .. $#ARRAY) {
delete $ARRAY[$index];

And so do these:

delete @HASH{keys %HASH};

delete @ARRAY[0 .. $#ARRAY];

But both of these are slower than just assigning the empty list
or undefining %HASH or @ARRAY:

%HASH = (); # completely empty %HASH
undef %HASH; # forget %HASH ever existed

@ARRAY = (); # completely empty @ARRAY
undef @ARRAY; # forget @ARRAY ever existed

Note that the EXPR can be arbitrarily complicated as long as the
final operation is a hash element, array element, hash slice, or
array slice lookup:

delete $ref->[$x][$y]{$key};
delete @{$ref->[$x][$y]}{$key1, $key2, @morekeys};

delete $ref->[$x][$y][$index];
delete @{$ref->[$x][$y]}[$index1, $index2, @moreindices];

I forgot that delete can also remove elements from an array slice.