Vijay
Vijay

Reputation: 67309

different type of value for each key in a hash

I searched in Google, but I did not find anything useful in it.

Even though there are many tutorials for Perl, I did not find any tutorial which would mention a hash which has different values for each and every key? Is such a thing possible in Perl?

For example, can there be a hash like which has 2 keys (a, b) where:

$myhash{"a"}=1;
$myhash{"b"}=[ 'hamnet', 'shakespeare', 'robyn', ];

Is the above possible?


I tried this:

#!/usr/bin/perl

use strict;
my %x;

$x{"a"}="b";
$x{"b"}=['c','d'];

foreach (keys %x)
{
  print $_."\n";
  print "$x{$_}";
}

but it is outputting:

a
bb
ARRAY(0x1ece50)

I am confused about how to access the elements of this hash.

I would like to tell you all that, even though I know Perl a bit, I am a complete novice regarding hashes.


OK, I found one thing — to access the array inside the hash, I need to do:

@{$x{"b"}}

But as I have told you, the value of a hash can be either an array or a scalar value, so for accessing the above hash, I need to initially identify the type of the value and then access it! How can I do this? That is, how can I identify whether a value for a key is either a scalar, an array or a hash?

Upvotes: 2

Views: 809

Answers (3)

Ilmari Karonen
Ilmari Karonen

Reputation: 50378

"Even though there are many tutorials for Perl, I did not find any tutorial which would mention a hash which has different values for each and every key? Is such a thing possible in Perl?"

You might've tried looking at the tutorials included in your Perl distribution, which include the Perl Data Structures Cookbook (perldsc). It includes a chapter on "More Elaborate Records", which gives examples on how to create and used a hash whose values have different types.

"But as I have told you, the value of a hash can be either an array or a scalar value, so for accessing the above hash, I need to initially identify the type of the value and then access it! How can I do this? That is, how can I identify whether a value for a key is either a scalar, an array or a hash?"

Since you seem to be a unfamiliar with the use of references and the ref operator, you may also want to take a look at Mark's very short tutorial about references (perlreftut).

Note that all of these tutorials (and many more) already come with your Perl distribution, and you can access them by typing e.g.

perldoc perlreftut

on the command line. (On some systems, you may need to install an extra package to enable the perldoc command. This is highly recommended if you intend to do any Perl programming at all.)

Upvotes: 3

memowe
memowe

Reputation: 2668

so for accessing the above hash i need to initially identify the type of the value and then access it!.How can i do this? i.e., how can i identify whether a value for a key is either a singular,array ,hash?

I think a clean solution to do this is to write a simple to_string function (no support for deeper nested structures) which identifies wether a value is a scalar, an array reference or a hash reference (which is what [...] creates: a reference to an anonymous array, see perlreftut). Read more about ref.

sub to_string {
    my $thing = shift;

    for (ref $thing) {

        # join with comma if $thing is an array ref
        return join ', ' => @$thing when 'ARRAY';

        # join key-value list with comma if $thing is a hash ref
        return join ', ' => map {"$_ => $thing->{$_}"} keys %$thing when 'HASH';

        # else: simply return the $thing itself
        return $thing;
    }
}

In a simple example program

my %data = (
    foo => 42,
    bar => [1, 2, 3],
    baz => {a => 'yay', b => 'nay'},
);

for my $key (keys %data) {
    say "$key: " . to_string($data{$key});
}

it will give you this output:

bar: 1, 2, 3
baz: a => yay, b => nay
foo: 42

Note that you have to

use feature qw(say switch);

for this program. HTH! :)

Upvotes: 1

slayedbylucifer
slayedbylucifer

Reputation: 23532

I think this what you want:

 #!/usr/bin/perl -w
 use strict;
 my %x;

 $x{"a"}="b";
 $x{"b"}=['c','d'];


 foreach my $a (keys %x)
 {
     if ( ref $x{$a} eq 'ARRAY' )
     {
         foreach my $b ( @{ $x{$a} } )
         {
             print $b."\n";
         }
     }
     else
     {
         print $x{$a}."\n";
     }
 }

Output:

# perl test.pl 
b
c
d

Check whether the hash value is an 'ARRAY' reference. If yes, then iterate over the array and print the values. Else, print the hash value rightaway.

Upvotes: 3

Related Questions