Perl · Course navigation

Perl stacks, queues, and word frequencies

Use push, pop, shift, and unshift as stack and queue operations, and count items with a hash.

On this page
Before you start

Perl arrays and hashes.

  • Use push, pop, shift, and unshift as stack and queue operations, and count items with a hash.
  • Predict the sample output and explain the state changes.
  • Complete the practice task and check the boundary cases.

The concept

A Perl array is also a stack and a queue. push adds at the end and pop removes from the end, which gives a last-in, first-out stack. shift removes from the front and unshift adds at the front, so push with shift is a first-in, first-out queue. All four operations are efficient, and no extra module is needed.

A hash makes counting easy. $freq{$word}++ creates the key with the value 1 the first time, because an undefined value counts as zero in numeric context. grep filters a list with a condition, map transforms each element, and the idiom grep { !$seen{$_}++ } removes duplicates while keeping the first occurrence of each item.

Code example

Perl
use strict;
use warnings;

my @stack;
push @stack, 1, 2, 3;
my $top = pop @stack;
print "$top @stack\n";

my @queue = (1, 2, 3);
my $front = shift @queue;
push @queue, 4;
print "$front @queue\n";
unshift @queue, 0;
print "@queue\n";

my $text = "the cat and the hat and the bat";
my %freq;
$freq{$_}++ for split ' ', $text;
print join(" ", map { "$_=$freq{$_}" } sort { $freq{$b} <=> $freq{$a} or $a cmp $b } keys %freq), "\n";

my @even = grep { $_ % 2 == 0 } 1 .. 10;
my @squares = map { $_ ** 2 } @even;
print "@even | @squares\n";

my %seen;
my @unique = grep { !$seen{$_}++ } qw(a b a c b);
print "@unique\n";
Output
3 1 2
1 2 3 4
0 2 3 4
the=3 and=2 bat=1 cat=1 hat=1
2 4 6 8 10 | 4 16 36 64 100
a b c

Follow the code

Open the walkthrough to inspect the example one step at a time.

Show guided walkthrough
Guided walkthroughReady
1use strict;
2use warnings;
3
4my @stack;
5push @stack, 1, 2, 3;
6my $top = pop @stack;
7print "$top @stack\n";
8
9my @queue = (1, 2, 3);
10my $front = shift @queue;
11push @queue, 4;
12print "$front @queue\n";
13unshift @queue, 0;
14print "@queue\n";
15
16my $text = "the cat and the hat and the bat";
17my %freq;
18$freq{$_}++ for split ' ', $text;
19print join(" ", map { "$_=$freq{$_}" } sort { $freq{$b} <=> $freq{$a} or $a cmp $b } keys %freq), "\n";
20
21my @even = grep { $_ % 2 == 0 } 1 .. 10;
22my @squares = map { $_ ** 2 } @even;
23print "@even | @squares\n";
24
25my %seen;
26my @unique = grep { !$seen{$_}++ } qw(a b a c b);
27print "@unique\n";

Follow the example

Start to inspect the source, values, and output. These prepared steps explain the published sample; grouped loop steps describe multiple iterations.

View the complete dry-run table
Prepared trace of the published program. Some rows group repeated iterations.
Step / lineWhat happensState after stepOutput so far
pop removes the last element: the most recently pushed one.—
—
3 came out; 1 and 2 remain.—
3 1 2
shift removes the first element: the oldest one.—
3 1 2
1 left the front; 4 joined the back.—
3 1 2
1 2 3 4
After unshift, 0 is at the front.—
3 1 2
1 2 3 4
0 2 3 4
Count every word. A missing key starts at zero.—
3 1 2
1 2 3 4
0 2 3 4
Highest counts first, ties broken alphabetically.—
3 1 2
1 2 3 4
0 2 3 4
the=3 and=2 bat=1 cat=1 hat=1
grep keeps the even numbers and map squares them.—
3 1 2
1 2 3 4
0 2 3 4
the=3 and=2 bat=1 cat=1 hat=1
2 4 6 8 10 | 4 16 36 64 100
!$seen{$_}++ is true only the first time an item is seen.—
3 1 2
1 2 3 4
0 2 3 4
the=3 and=2 bat=1 cat=1 hat=1
2 4 6 8 10 | 4 16 36 64 100
a b c

Behind the scenes

How Perl processes this code

Perl compiles the script internally before executing it. strict and warnings help identify mistakes.

Cost and common mistakes

push, pop, shift, and unshift are O(1) amortized. Counting is O(n).

  • shift and pop on an empty array return undef, and with use warnings, printing undef gives a warning.
  • In grep and map blocks, $_ is the current element and is an alias to the original. Modifying it changes the array.
  • Hash order is random. Sort the keys whenever the output order matters.

Try it yourself

How would you count only words longer than three letters?

Reveal answer and reasoning

Add a condition: $freq{$_}++ for grep { length($_) > 3 } split ' ', $text;

Further reading