How to pass a hash in Perl

Task. In the code of the Perl program there is a hash %h. In this hash there are some pairs of values. You need to go through all the hash items and perform actions with each item.

Walk through the hash using foreach

Most often, the most convenient way to bypass the hash is to use foreach. Here is an example code:

▶ Run
#!/usr/bin/perl

my %h = (
    a => 1,
    b => 20,
    asdf => 'Hello',
);

foreach my $key (keys %h) {
    print "$key - $h{$key}\n";
}

It's all quite simple. First we create a hash %h which has three pairs of values. Next is a cycle. Using keys %h we obtained a list of all hash keys (in this example, line 'a', 'b' and 'asdf'). The key string is written into a variable $key , and executes the loop body, then in $key fits the following hash key and again executes the loop body, and this happens for all keys.

If you save this code to a file script.pl and run it perl script.pl, then the screen will appear a set of pairs of values contained in the hash:

b - 20
asdf - Hello
a - 1

A hash is an unordered set of values. And the conclusion is clearly visible — the order in which it was withdrawn the elements of the hash does not match the order in which they were defined in the program code. And if you run this script several times, the order of elements in the output will change. keys %h returns the list of keys hash in an arbitrary order. If you need to order was always the same, for example, you can use sorting foreach my $key (sort keys %h) {.

Pass the hash using while and each

Another way to circumvent the entire hash is to use a loop while and the key word each. Here is the code which works similarly to the previous example:

▶ Run
#!/usr/bin/perl

my %h = (
    a => 1,
    b => 20,
    asdf => 'Hello',
);

while (my ($key, $value) = each %h) {
    print "$key - $value\n";
}

each %h returns a list of two elements — a hash key and its corresponding value. Exactly the same as in the case keys the order in which each returns pairs of values is not defined. Different runs of the same the program will return the pairs in different orders.

We assign the values which are returned each in variables. each remembers which pairs of the hash he was given the next time you use returns a different value pairs. This will continue until each does not return all the pairs, then it will return an empty list. While each returns a couple of values, executes the body of while cycle, once it returns an empty list cycle whileis completed.

Change the values in the hash

When using foreach cycle keys %h is executed only once. When using whilecycle each is performed at each iteration.

Extend the previous problem — we need not only to display all of the elements of the hash, but also to replace them. It is absolutely no problem when using foreach and keys:

▶ Run
#!/usr/bin/perl

use Data::Dumper;

my %h = (
    a => 1,
    b => 20,
    asdf => 'Hello',
);

foreach my $key (keys %h) {
    print "$key - $h{$key}\n";
    $h{ $key . $key } = $h{$key};
    delete $h{$key};
}

print Dumper \%h;

The output of the program:

asdf - Hello
a - 1
b - 20
$VAR1 = {
          'bb' => 20,
          'aa' => 1,
          'asdfasdf' => 'Hello'
        };

It doesn't work to make when to use each:

▶ Run
#!/usr/bin/perl

use Data::Dumper;

my %h = (
    a => 1,
    b => 20,
    asdf => 'Hello',
);

while (my ($key, $value) = each %h) {
    print "$key - $value\n";

    # error!
    $h{ $key . $key } = $value;
    delete $h{$key};
}

print Dumper \%h;

When you run this program on the screen will appear something like:

Use of each() on hash after insertion without resetting hash iterator results in undefined behavior at script.pl line 11.
Use of each() on hash after insertion without resetting hash iterator results in undefined behavior at script.pl line 11.
Use of each() on hash after insertion without resetting hash iterator results in undefined behavior at script.pl line 11.
Use of each() on hash after insertion without resetting hash iterator results in undefined behavior at script.pl line 11.
b - 20
bb - 20
bbbb - 20
asdf - Hello
$VAR1 = {
          'asdfasdf' => 'Hello',
          'bbbbbbbb' => 20,
          'a' => 1
        };

each returned value pair from the hash, and then we change the hash. Is the following iteration of the loop and eachreturns a couple of the modified hash, and it can return the pair that you just added.

So if the bypass hash need to change it, you need to use foreach and keys. When using while and each program will not work correctly.

Related topics

Other articles

Comments