splice#
Remove and/or replace a slice of an array in place, and return the removed elements.
splice is the general-purpose array surgeon. Every other array
mutator — push, pop, shift, unshift, single-element
assignment — can be written as a splice call. Pick the position
with OFFSET, pick how many elements to cut with LENGTH, and
optionally supply a LIST of replacements. The array grows or
shrinks to fit, and you get back whatever was cut out.
Synopsis#
splice @array; # remove everything
splice @array, $offset; # remove from $offset to the end
splice @array, $offset, $length; # remove $length elements
splice @array, $offset, $length, @list; # remove and replace with @list
What you get back#
List context: the list of elements that were removed, in their original order. Empty list if nothing was removed.
Scalar context: the last element removed, or
undefif nothing was removed. This is rarely what you want — reach for list context unless you specifically need only the tail.Void context: nothing; use this form when you only care about the in-place mutation.
Examples#
Basic removal — cut two elements starting at index 1:
my @a = ('a', 'b', 'c', 'd', 'e');
my @gone = splice @a, 1, 2;
# @a == ('a', 'd', 'e')
# @gone == ('b', 'c')
Insert without removing — LENGTH is 0, so nothing comes out and
the LIST is spliced in at OFFSET:
my @a = (1, 2, 5, 6);
splice @a, 2, 0, 3, 4;
# @a == (1, 2, 3, 4, 5, 6)
Replace a fragment — LENGTH and replacement size need not match.
Here three elements leave, one arrives:
my @a = ('x', 'y', 'z', 'w', 'v');
my @gone = splice @a, 1, 3, 'Y';
# @a == ('x', 'Y', 'v')
# @gone == ('y', 'z', 'w')
Remove the trailing tail — omit LENGTH entirely to cut from
OFFSET to the end:
my @a = (1, 2, 3, 4, 5);
my @tail = splice @a, 3;
# @a == (1, 2, 3)
# @tail == (4, 5)
Negative OFFSET counts from the end. Pop the last element:
my @a = ('a', 'b', 'c');
my $last = splice @a, -1;
# @a == ('a', 'b')
# $last == 'c'
Classic idiom — consume an array $n elements at a time:
while (my @chunk = splice @queue, 0, $n) {
process(@chunk);
}
All the common array primitives written as splice (assuming
$#a >= $i):
push @a, $x, $y; # splice @a, scalar(@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
Edge cases#
Negative
OFFSETcounts from the end:-1is the last element,-2the one before, and so on. If the magnitude exceeds the array length, Perl issues a warning and clamps to0.Negative
LENGTHleaves that many elements at the end of the array untouched.splice @a, 2, -1removes from index2up to but not including the final element.OFFSETpast the end: with an explicitLENGTH, Perl issues a warning and splices at the end of the array (equivalent tosplice @a, scalar(@a), 0, LIST). Without aLENGTH, nothing is removed.LENGTHpast the end: silently clamped.splice @a, 1, 999simply removes everything from index1onward.Both
OFFSETandLENGTHomitted: removes every element. The array is left empty.Replacement list size differs from
LENGTH: the array grows or shrinks to match. There is no requirement thatscalar(@list)equalLENGTH— that asymmetry is the whole point ofsplice.Array reference: dereference inline.
splice @$ref, 0, 1andsplice @{ $obj->{items} }, -2both work.Splicing a slice is not supported:
splice @a[1..3], 0, 1is a syntax error.splicerequires a named array or dereferenced array, not a list expression. To operate on a range, pass the bounds asOFFSETandLENGTHinstead.Void context is fine. If the return value is not needed, call
spliceas a statement — no allocation of the removed-elements list happens in that case.Scalar expressions as the first argument: not allowed. An experimental feature permitted this from 5.14 through 5.22 and was removed in 5.24. The first argument must be an array (or dereferenced arrayref).
Differences from upstream#
Fully compatible with upstream Perl 5.42.
See also#
push— append to the end; equivalent tosplice @a, scalar(@a), 0, LISTpop— remove the last element; equivalent tosplice @a, -1shift— remove the first element; equivalent tosplice @a, 0, 1unshift— prepend; equivalent tosplice @a, 0, 0, LISTdelete— superficially similar but semantically different.delete $a[$i]leaves a hole (the slot becomesundef) and does not renumber later indices; the array’s length is unchanged unless the deleted slot was the last one.splice @a, $i, 1physically removes the slot and shifts every later element down by one. Usedeletefor sparse arrays where index identity matters; usesplicewhen you want the array to close up.grep— filter an array into a new one by predicate; reach for it instead ofsplicewhen you want “keep only the ones that match” rather than “cut out a contiguous range”