Given a hash of some of the capitals of the world

my %capital_of = (
Tuvalu     => 'Funafuti',
Zimbabwe   => 'Harare',
Eritrea    => 'Asmara',
Botswana   => 'Gaborone',
);

How can we get several values out of it in one step?

Earlier we saw how to get a slice of an array or an array reference, this time we do something similar with hashes.

## Hash slice

If we have a hash like the %capital_of above we can access individual elements in it using \$ prefix and curly braces after the name:

We can also create a list of some of the values be creating a list of these values:

(\$capital_of{'Zimbabwe'}, \$capital_of{'Eritrea'}, \$capital_of{'Botswana'})

We can assign them names of the capitals to an array:

my @african_capitals = (\$capital_of{'Zimbabwe'}, \$capital_of{'Eritrea'}, \$capital_of{'Botswana'});

print Dumper \@african_capitals;

\$VAR1 = [
'Harare',
'Asmara',
'Gaborone'
];

If course listing "\$hash_of" 3 times is already too much for most of us, but if we had to list the capitals of all the African countries that would be really too much repetition.

Instead of that we use a syntax called hash slice. It returns a list of values. In this syntax we put a @ in front of the name of the hash and put curly braces {} after it. Within the curly braces we put one or more keys of the hash. This will return the values of the appropriate keys.

my @african_capitals = @capital_of{'Zimbabwe', 'Eritrea', 'Botswana'};

Results in the same list of capitals.

If you want to avoid the quotes and spaces you can also use qw:

my @african_capitals = @capital_of{qw(Zimbabwe Eritrea Botswana)};

The same would work no matter how we supply the keys of the hash, (the names of African countries). It can be an expression including a function returning names or an array holding the names like here:

my @countries_in_africa = qw(Zimbabwe Eritrea Botswana);
my @african_capitals = @capital_of{ @countries_in_africa };

## Hash slice on the left-hand side

The same syntax can also be used on the left-hand side of the equation. For example:

@capital_of{'Belize', 'Kyrgyzstan'} = ('Belmopan', 'Bishkek');

print Dumper \%capital_of;

\$VAR1 = {
'Tuvalu' => 'Funafuti',
'Eritrea' => 'Asmara',
'Zimbabwe' => 'Harare',
'Kyrgyzstan' => 'Bishkek',
'Belize' => 'Belmopan',
'Botswana' => 'Gaborone'
};

Here too we could use any expression in place of either of the lists:

my @countries = ('Belize', 'Kyrgyzstan');
my @capitals = ('Belmopan', 'Bishkek');
@capital_of{ @countries } = @capitals;

## Example

See the full sample script I used to generate the code snippets:

examples/hash_slices.pl

use strict;
use warnings;
use Data::Dumper qw(Dumper);

my %capital_of = (
Tuvalu     => 'Funafuti',
Zimbabwe   => 'Harare',
Eritrea    => 'Asmara',
Botswana   => 'Gaborone',
);

#my @african_capitals = @capital_of{'Zimbabwe', 'Eritrea', 'Botswana'};
#my @african_capitals = @capital_of{qw(Zimbabwe Eritrea Botswana)};
my @countries_in_africa = qw(Zimbabwe Eritrea Botswana);
#my @african_capitals = @capital_of{ @countries_in_africa };

#print Dumper \@african_capitals;

#@capital_of{'Belize', 'Kyrgyzstan'} = ('Belmopan', 'Bishkek');

my @countries = ('Belize', 'Kyrgyzstan');
my @capitals = ('Belmopan', 'Bishkek');
#@capital_of{ @countries } = @capitals;

#print Dumper \%capital_of;