24

Up until recently, I've been storing multiple values into different hashes with the same keys as follows:

%boss = (
    "Allan"  => "George",
    "Bob"    => "George",
    "George" => "lisa" );

%status = (
    "Allan"  => "Contractor",
    "Bob"    => "Part-time",
    "George" => "Full-time" );

and then I can reference $boss("Bob") and $status("Bob") but this gets unwieldy if there's a lot of properties each key can have and I have to worry about keeping the hashes in sync.

Is there a better way for storing multiple values in a hash? I could store the values as

        "Bob" => "George:Part-time"

and then disassemble the strings with split, but there must be a more elegant way.

Axeman
  • 29,660
  • 2
  • 47
  • 102
paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953

5 Answers5

26

This is the standard way, as per perldoc perldsc.

~> more test.pl
%chums = ( "Allan" => {"Boss" => "George", "Status" => "Contractor"},
           "Bob" => {"Boss" => "Peter", "Status" => "Part-time"} );

print $chums{"Allan"}{"Boss"}."\n";
print $chums{"Bob"}{"Boss"}."\n";
print $chums{"Bob"}{"Status"}."\n";
$chums{"Bob"}{"Wife"} = "Pam";
print $chums{"Bob"}{"Wife"}."\n";

~> perl test.pl
George
Peter
Part-time
Pam
Brad Gilbert
  • 33,846
  • 11
  • 78
  • 129
Vinko Vrsalovic
  • 330,807
  • 53
  • 334
  • 373
  • That looks okay. I guess I can add another chum with $chums{"Greg"} = {"Boss" => "Lisa", "Status" => "Fired"} but how do I go about adding a wife to Bob? Would that be $chums{"Bob"}{"Wife"} = "Carol"? – paxdiablo Oct 10 '08 at 08:11
  • Also, why the "->". It seems to function without these. – paxdiablo Oct 10 '08 at 08:13
  • 2
    TIMTOWDI :), you can use it without them, and yes, your way to add a wife is correct – Vinko Vrsalovic Oct 10 '08 at 08:21
  • This is a great reminder of the value of the perldsc. This should be required reading for PHP, Python, Ruby and Perl programmers. – dreftymac Jul 09 '13 at 22:40
23

Hashes of hashes is what you're explicitly asking for. There is a tutorial style piece of documentation part of the Perl documentation which covers this: Data Structure Cookbook But maybe you should consider going object-oriented. This is sort of the stereotypical example for object oriented programming tutorials.

How about something like this:

#!/usr/bin/perl
package Employee;
use Moose;
has 'name' => ( is => 'rw', isa => 'Str' );

# should really use a Status class
has 'status' => ( is => 'rw', isa => 'Str' );

has 'superior' => (
  is      => 'rw',
  isa     => 'Employee',
  default => undef,
);

###############
package main;
use strict;
use warnings;

my %employees; # maybe use a class for this, too

$employees{George} = Employee->new(
  name   => 'George',
  status => 'Boss',
);

$employees{Allan} = Employee->new(
  name     => 'Allan',
  status   => 'Contractor',
  superior => $employees{George},
);

print $employees{Allan}->superior->name, "\n";
tsee
  • 5,034
  • 1
  • 19
  • 27
4

Hashes can contain other hashes or arrays. If you want to refer to your properties by name, store them as a hash per key, otherwise store them as an array per key.

There is a reference for the syntax.

brian d foy
  • 129,424
  • 31
  • 207
  • 592
moonshadow
  • 86,889
  • 7
  • 82
  • 122
2
my %employees = (
    "Allan" => { "Boss" => "George", "Status" => "Contractor" },
);

print $employees{"Allan"}{"Boss"}, "\n";
Swaroop C H
  • 16,902
  • 10
  • 43
  • 50
0

%chums = ( "Allan" => {"Boss" => "George", "Status" => "Contractor"}, "Bob" => {"Boss" => "Peter", "Status" => "Part-time"} );

works great but is there a faster way to enter the data?

I am thinking of something like

%chums = (qw, x)( Allan Boss George Status Contractor Bob Boss Peter Status Part-time)

where x = the number of secondary keys after the primary key, in this case x = 2, "Boss" and "Status"