Nested data structures

Contents
Array of hashes
Hash of arrays
Walk nested data
Inspect with Data::Dumper
Shallow and deep copy

Array of hashes

Records usually become an array of hash references: the array keeps the order, and each hash holds the fields of one row. The arrow between the two indexes is the only new syntax you need.

my @users = ( { name => "Ada", age => 36 }, { name => "Grace", age => 45 }, ); print $users[1]{name}, "\n"; # Grace

perl demo.pl

Grace

Between two subscripts the arrow may be omitted, so $users[1]{name} is the same as $users[1]->{name}. Keep the arrow when a reference is involved and the reader will thank you.

Hash of arrays

The mirror shape groups several values under one key. A hash of array references is the natural way to store, say, all log lines per host.

my %by_host = ( db1 => ["ok", "ok"], db2 => ["fail"], ); push @{$by_host{db2}}, "ok"; print @{$by_host{db2}}, "\n"; # failok, print adds no separator

perl demo.pl

failok

The braces around $by_host{db2} tell Perl where the key ends before it dereferences the array. Writing @$by_host{db2} would mean something else entirely, a hash slice.

Walk nested data

Two nested loops read any array of hashes. Name the row variable and the fields stay obvious even in a long block.

my @users = ({ name => "Ada", age => 36 }, { name => "Grace", age => 45 }); my %by_host = (db1 => ["ok", "ok"], db2 => ["fail", "ok"]); for my $user (@users) { print "$user->{name} is $user->{age}\n"; } for my $host (sort keys %by_host) { print "$host: ", scalar @{$by_host{$host}}, "\n"; }

perl demo.pl

Ada is 36
Grace is 45
db1: 2
db2: 2

Inspect with Data::Dumper

Printing a reference shows something like HASH(0x55d1c8), which tells you nothing. Data::Dumper is in the core, so it is always available, and it prints the whole structure as Perl source.

my @users = ({ name => "Ada", age => 36 }, { name => "Grace", age => 45 }); use Data::Dumper; $Data::Dumper::Sortkeys = 1; print Dumper(\@users);

perl demo.pl

$VAR1 = [ { 'age' => 36, 'name' => 'Ada' }, { 'age' => 45, 'name' => 'Grace' } ];

$Data::Dumper::Sortkeys = 1; fixes the key order, because a hash hands out its keys in a different order on every run. Leave it out and the same script prints the fields of each record in a new sequence each time.

Shallow and deep copy

Assigning a reference copies the pointer, not the data: both names then change the same structure. Copy the top level with [@list] or {%hash}, and use Storable for a full deep copy.

my @users = ({ name => "Ada", age => 36 }, { name => "Grace", age => 45 }); use Storable qw(dclone); my $copy = dclone(\@users); $copy->[0]{age} = 99; print $users[0]{age}, "\n"; # 36, original untouched

perl demo.pl

36

Shallow copies are enough when the nested references are never modified. Reach for dclone the moment you plan to write into a structure that someone else also holds.

Next: Regular expressions: match and anchors

Article author: Arthur Isaev

Related articles
Perl
Perl course: zero to hero in 50 lessons
What is Perl and where it runs
Install Perl and check the version
Your first Perl script
The debugger as a REPL
Scalars and sigils
Numbers
Strings
Interpolation and quoting
Arrays
push, pop, shift and splice
Hashes
keys, values, exists and delete
Scalar and list context
Conditions and comparison
while, for, next and last
foreach and the default variable
Subroutines
Arguments in @_
References
Nested data structures
Regular expressions: match and anchors
Captures and named groups
Substitution with s///
split and join
grep and map
Sort and the Schwartzian transform
Read and write files
File tests and metadata
Directories and paths
die, warn and eval
Modules and Exporter
CPAN and cpanm
Objects with bless
Modern objects with Moo
Testing with Test::More
strict, warnings and diagnostics
Options with Getopt::Long
Environment and %ENV
system, backticks and pipes
One-liners with -n and -p
CSV and TSV processing
JSON with JSON::PP
HTTP clients with HTTP::Tiny
Sockets and IO::Socket
Databases with DBI
Capstone: todo CLI
Capstone: log report
Performance and profiling
Modern Perl tour
Hero roadmap: the whole course on one page
Install Perl on Windows 11
Install Perl on Ubuntu
Install Perl on Rocky Linux
Install Perl on macOS
Install Perl on FreeBSD
Perl in Docker

Search this site

Channel @aofeed Chat @aofeedchat

Contacts and cooperation:
I recommend our hosting beget.com
Write to info@aredel.com if you:
1. Want to write an article for our site or translate an article into your native language.
2. Want to place thematically relevant ads on the site.
3. Ads on my site pass maximum censorship. If you see an ad block unsuitable for school-age children, shocking or misleading - please contact us by e-mail
4. Found a mistake, inaccuracy, bug, etc. on the site. ... .......
5. Articles can be shared on social media by clicking a network icon: