Perl v5.20 introduced key-value slices that worked on hashes and arrays. You could extract values by their keys or indices as well as assigning to those.
The key-value slice delete is way to extract the keys and values you want and delete them at the same time. You can destructively
A review of delete
The delete removes the element from the hash or array and returns it.
use v5.10; my %hash = qw( Cat Buster Dog Addy Bird Foghorn Lizard Godzilla ); my $removed_value = delete $hash{'Lizard'}; say "Removed $removed_value"; say Dumper( \%hash );
The delete removed the Lizard
key and returned its value:
Removed Godzilla $VAR1 = { 'Bird' => 'Foghorn', 'Dog' => 'Addy', 'Cat' => 'Buster' };
A delete on a slice does the same thing. The @
before hash
signifies multiple values (not an array!) and you know it’s a hash variable because the indexing uses {}
:
use v5.10; use Data::Dumper; my %hash = qw( Cat Buster Dog Addy Bird Foghorn Lizard Godzilla ); my @removed_values = delete @hash{ qw(Lizard Bird) }; say "Removed @removed_values"; say Dumper( \%hash );
The delete returns the values from the keys it deleted:
Removed Godzilla Foghorn $VAR1 = { 'Cat' => 'Buster', 'Dog' => 'Addy' };
This works on arrays too even though the documentation says you shouldn’t use them. The “key” doesn’t necessarily disappear. Interior items become undef and items at the end disappear:
Removed Addy Godzilla $VAR1 = [ 'Buster', undef, 'Foghorn' ];
One of the “keys” (the one that was at the end) is apparently gone but the interior “key” is still present but now has an undef
value. Maybe that works for you but I’m guessing your maintenance programmer won’t know that.
The key-value slice
The key-value slice extracts the keys and the values at the same time. It returns a list (maybe of zero items if the key does not exist):
use v5.20; my %hash = qw( Cat Buster Dog Addy Bird Foghorn Lizard Godzilla ); say join ' ', %hash{ qw(Bird Lizard) }
The output shows the keys and their values:
Bird Foghorn Lizard Godzilla
This works on an array and uses the indices as the keys and square braces to surround those keys. There’s still a %
in front of the variable name to signify that it’s a key-value slice but you use the square brackets for the indices (Item 4. Understand what sigils are telling you.):
use v5.20; my @array = qw( Buster Addy Foghorn Godzilla ); my @indices = ( 1, 3 ); my @sliced = %array[@indices]; say "@sliced";
Now the keys are the list indices. This can be useful when you don’t know ahead of time what the indices are but still need to match them up with their values:
1 Addy 3 Godzilla
This is certainly more palatable than computing the intermediate results and merging the indices later:
my @indices = ( 1, 3 ); my @values = @array[@indices]; my @sliced = zip( @indices, @values );
Destructive processing with key-value slices
Deleting a key-value slice removes the elements (sets them to undef
if an array) and removes those key-values at the same time.
Suppose that show_items
does some complicated and interesting task. It needs to know which value it is processing and what that value belongs to. The key-value delete
provides the keys and values together and removes them from the things to process:
use v5.28; my %hash_to_process = qw( Cat Buster Dog Addy Bird Foghorn Lizard Godzilla ); my @items_to_process = qw(Bird Lizard); process( delete %hash_to_process{ @items_to_process } ) sub process { say "Processing @_" }
Things to remember
- A classic
delete
returns the value - A key-value
delete
returns both the key and the value - The
%
signifies a key-value slice for either a hash or an array