How to Add Elements to an Array in Perl (push, unshift, splice, indexing, and arrayrefs)
Question
how to add elements to an array perl
Difficulty: Beginner → Intermediate
Tags: perl, arrays, push, unshift, splice, indexing, arrayref, best-practices
Overview
In Perl, an array is an ordered list of scalar values. Arrays are one of Perl’s core data types and are extremely flexible: you can grow them, shrink them, insert into the middle, prepend to the front, and even assign to specific indexes far beyond the current length (creating “holes”).
The most common ways to add elements to an array are:
- Append to the end with
push - Prepend to the beginning with
unshift - Insert (or replace) anywhere with
splice - Assign by index (including extending the array)
- Concatenate lists by building a new array (useful, but less efficient in loops)
- Work with array references using
push @{ $aref }, ...
Perl array basics (quick refresher)
In Perl, @array refers to the entire array in list context. Individual elements are scalars and are accessed with $array[index]. This is a common source of confusion for beginners:
@namesis the whole array (list)$names[0]is the first element (scalar)
Most array-growing operations happen in-place (they modify the array directly), which is usually what you want.
1) Add elements to the end: push
push appends one or more elements to the end of an array:
push @a, $x;appends one elementpush @a, $x, $y, $z;appends multiple elementspush @a, @b;appends all elements of@b(flattened)
Important: push returns the new length of the array, not the array itself.
Runnable example 1 (push + unshift + splice)
use strict;
use warnings;
my @a = (1, 2);
push @a, 3; # add to end
unshift @a, 0; # add to beginning
splice @a, 2, 0, 1.5;# insert at index 2, delete 0, insert 1.5
print join(",", @a), "\n";
Expected output:
0,1,1.5,2,3
2) Add elements to the beginning: unshift
unshift prepends one or more elements to the front of the array. Existing elements move to higher indexes to make room:
unshift @a, $x;prepends one elementunshift @a, $x, $y;prepends multiple elements
Performance note: Because every existing element must be moved, repeated unshift operations on very large arrays can be slower than push. If you need stack-like behavior, use push/pop. For queue-like behavior, push/shift is common, but for very large queues you might consider a different structure (or modules) if performance becomes an issue.
3) Insert (or replace) anywhere: splice
splice is the most powerful array-editing tool. It can:
- Insert into the middle
- Delete a range
- Replace a range with new elements
The common form is:
splice @array, $offset, $length, @replacement;
$offset: where to start (0-based). Negative offsets count from the end.$length: how many elements to remove@replacement: optional list to insert in place of removed elements
To insert without deleting, set $length to 0 (as in Example 1).
Common pitfall: splice returns the removed elements. If you accidentally assign it back, you may overwrite your data:
# Wrong if you meant to modify @a in-place:
@a = splice(@a, 2, 0, "x"); # @a becomes the removed items (often empty!)
The correct in-place usage is typically just:
splice @a, 2, 0, "x";
4) Add/extend by assigning to an index
You can assign directly to an index to set or add an element:
my @a;
$a[0] = "first"; # adds at index 0
$a[3] = "fourth"; # extends array, indexes 1 and 2 become undef
If you assign to an index beyond the current end, Perl extends the array and fills the gap with undef values. Those “holes” can surprise you later when you iterate or join the array.
Runnable example 2 (index assignment + appending multiple items)
use strict;
use warnings;
my @colors;
$colors[2] = "blue"; # array auto-extends
$colors[0] = "red";
$colors[1] = "green";
print join(" ", @colors), "\n";
push @colors, qw(yellow purple);
print scalar(@colors), "\n";
Expected output:
red green blue
5
Because we set indexes 0, 1, and 2, there are no holes. If we had only set $colors[2] and printed immediately, the first two elements would have been undef (which can print as empty strings under join).
5) Add multiple elements by list concatenation (useful, but be careful in loops)
You can create a new array containing old and new elements using list construction:
@a = (@a, $new_value); # append one
@a = ($new_value, @a); # prepend one
@a = (@a, @more_values); # append many
This is perfectly valid and sometimes reads nicely in small scripts. However, it generally creates a new list and can be less efficient than push/unshift, especially inside large loops.
Best practice: prefer push for repeated appends and unshift for occasional prepends; reserve list concatenation for one-off transformations or when you specifically want to create a new array value (for example, when you do not want to mutate the original).
6) Adding elements to array references (arrayrefs)
In real programs, you often work with array references (especially in data structures or when passing arrays to subroutines without copying). If $aref is an array reference, you add elements like this:
push @{ $aref }, $x;unshift @{ $aref }, $x;splice @{ $aref }, $offset, $len, @repl;
Runnable example 3 (arrayref push/unshift)
use strict;
use warnings;
my $aref = [];
push @$aref, "alpha";
push @$aref, qw(beta gamma);
unshift @$aref, "start";
print join("->", @$aref), "\n";
Expected output:
start->alpha->beta->gamma
Notice the shorthand: push @$aref, ... is equivalent to push @{ $aref }, .... Both are common; the shorter form is idiomatic when it stays readable.
Best practices
- Use
use strict; use warnings;in scripts and modules. It catches many common mistakes early, especially typos and accidental global variables. - Prefer
pushfor building lists (especially in loops). It is idiomatic and avoids repeated list copying. - Be explicit about what you’re pushing:
push @a, @b;flattens@b. If you intended to push a reference to@bas a single element, dopush @a, \@b;. - Watch out for holes when assigning to far indexes (they become
undef). If you need a dense list, build it withpushor ensure all intermediate values are set. - Use
splicesparingly and clearly. It’s powerful but easier to get wrong. Consider extracting intent into helper subs if the offsets/lengths are complex. - Don’t confuse return values:
push/unshiftreturn the new length;splicereturns removed elements.
Common pitfalls (and how to avoid them)
- Accidentally overwriting your array with
push’s return value:
Correct usage is justmy @a; @a = push @a, 1; # WRONG: @a becomes (1) because push returns new lengthpush @a, 1;(no assignment), or capture the length in a scalar:my $len = push @a, 1;. - Forgetting the sigil difference:
@avs$a[0]. Remember: element access uses$because it’s a scalar. - Joining arrays with
undefholes: holes turn into empty strings underjoinand can hide bugs. If you suspect holes, check with something like:
for my $i (0..$#a) { print "$i: ", (defined $a[$i] ? $a[$i] : "(undef)"), "\n"; } - Pushing an array reference when you meant to flatten (or vice versa). Know whether you want one element (a reference) or many (a list).
- Using list concatenation in a hot loop:
@a = (@a, $x)repeatedly can be noticeably slower thanpush @a, $xfor large data sets.
Real-world usage patterns
Pattern A: Build a list from input
When reading lines from a filehandle and collecting them, push is the standard tool:
my @lines;
while (my $line = <STDIN>) {
chomp $line;
push @lines, $line;
}
This produces a clean, dense list in the order read.
Pattern B: Insert markers or headers
If you need to add a header before a list of rows (for example, a CSV header), unshift is direct:
unshift @rows, "id,name,email";
Pattern C: Maintain a small rolling window
A common approach is to push new items and shift old ones to keep only the last N values:
push @window, $value;
shift @window while @window > 100;
This is simple and effective for moderate sizes; if N is huge and performance matters, you might consider alternative structures, but for many applications it’s plenty.
Summary
To add elements to a Perl array, the idiomatic choices are push (append) and unshift (prepend). For inserting or replacing elements at arbitrary positions, use splice. You can also extend arrays by direct index assignment, but be aware it can create undef holes. In real programs, you’ll often do the same operations on array references using push @$aref, .... Stick with use strict and use warnings, understand the return values of these functions, and you’ll avoid most common array-growth bugs.
Verified Code
Executed in a sandbox to capture real output. • 5ms
0,1,1.5,2,3
(empty)Was this helpful?
Related Questions
- How to Write to a File in Perl (open/print, modes, safety, and best practices)
- How to Load a Module in Perl (use, require, @INC, and Best Practices)
- How to Run Perl Code on macOS (Terminal, Scripts, Shebangs, Modules, and Common Pitfalls)
- How to Install Perl Modules on Windows (CPAN, cpanm, Strawberry Perl, ActiveState, local::lib)
- How to Compare Strings in Perl (eq/ne, lt/gt, cmp, case-insensitive, Unicode)
- How to Check If a Perl Module Is Installed (and Loadable)