Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I copy list elements to hash keys in perl?

I have found a couple of ways to copy the elements of a list to the keys of a hash, but could somebody please explain how this works?

#!/usr/bin/perl
use v5.34.0;

my @arry = qw( ray bill lois shirly missy hank );

my %hash;
$hash{$_}++ for @arry;  # What is happening here?

foreach (keys %hash) {
  say "$_ => " . $hash{$_};
}

The output is what I expected. I don't know how the assignment is being made.

hank => 1
shirly => 1
missy => 1
bill => 1
lois => 1
ray => 1
like image 803
user3834254 Avatar asked Nov 16 '25 03:11

user3834254


1 Answers

$hash{$_}++ for @array;

Can also be written

for (@array) {
    $hash{$_}++;
}

Or more explicitly

for my $key (@array) {
    $hash{$key}++;
}

$_ is "the default input and pattern-searching space"-variable. Often in Perl functions, you can leave out naming an explicit variable to use, and it will default to using $_. for is an example of that. You can also write an explicit variable name, that might feel more informative for your code:

for my $word (@words) 

Or idiomatically:

for my $key (keys %hash)    # using $key variable name for hash keys

You should also be aware that for and foreach are exactly identical in Perl. They are aliases for the same function. Hence, I always use for because it is shorter.

The second part of the code is the assignment, using the auto-increment operator ++

It is appended to a variable on the LHS and increments its value by 1. E.g.

$_++           means $_ = $_ + 1
$hash{$_}++    means $hash{$_} = $hash{$_} + 1
...etc

It also has a certain Perl magic included, which you can read more about in the documentation. In this case, it means that it can increment even undefined variables without issuing a warning about it. This is ideal when it comes to initializing hash keys, which do not exist beforehand.

Your code will initialize a hash key for each word in your @arry list, and also count the occurrences of each word. Which happens to be 1 in this case. This is relevant to point out, because since hash keys are unique, your array list may be bigger than the list of keys in the hash, since some keys would overwrite each other.

my @words = qw(foo bar bar baaz);
my %hash1;

for my $key (@words) {
    $hash{$key} = 1;       # initialize each word
}

# %hash1 = ( foo => 1, bar => 1, baaz => 1 );
#                      note -^^

my %hash2;    # new hash
for my $key (@words) {
    $hash{$key}++;         # use auto-increment: words are counted
}

# %hash2 = ( foo => 1, bar => 2, baaz => 1);    
#                      note -^^ 
like image 168
TLP Avatar answered Nov 17 '25 20:11

TLP