http://www.perlmonks.org?node_id=1043398

Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

My current knowledge of hashes is to create a hash with unique keys. So, if given a group of people, I can create something like this:
'Bob Dole' => { 'address' => '123 peach st.', 'spouse' => 'Bill Clinton', 'father' => 'Frank Dole' }, 'Al Pacino' => { 'address' => '123 orange st.', 'spouse' => 'Robert Deniro', 'father' => 'Marlon Brando' } ...
What I am trying to figure out how to create is something like this instead:
'People' => { 'name' => 'Bob Dole', 'address' => '123 peach st.', 'spouse' => 'Bill Clinton', 'father' => 'Frank Dole' }, { 'name' => 'Al Pacino', 'address' => '123 orange st.', 'spouse' => 'Robert Deniro', 'father' => 'Marlon Brando' } ...
I'm having a difficult time finding the right search terms to get some sort of tutorial that helps me with this one. A nudge in the right direction would be greatly appreciated.

Replies are listed 'Best First'.
Re: Question regarding hash with multiple values
by toolic (Bishop) on Jul 10, 2013 at 01:02 UTC
Re: Question regarding hash with multiple values
by AnomalousMonk (Archbishop) on Jul 10, 2013 at 05:09 UTC

    Based on toolic's link and with your data as example:

    >perl -wMstrict -MData::Dump -le "my %HoAoH = ( 'People' => [ { 'name' => 'Bob Dole', 'address' => '123 peach st.', 'spouse' => 'Bill Clinton', 'father' => 'Frank Dole' }, { 'name' => 'Al Pacino', 'address' => '123 orange st.', 'spouse' => 'Robert Deniro', 'father' => 'Marlon Brando' }, ], ); ;; dd \%HoAoH; ;; print $HoAoH{People}[1]{name}; print $HoAoH{People}[1]{address}; " { People => [ { address => "123 peach st.", father => "Frank Dole", name => "Bob Dole", spouse => "Bill Clinton", }, { address => "123 orange st.", father => "Marlon Brando", name => "Al Pacino", spouse => "Robert Deniro", }, ], } Al Pacino 123 orange st.

      n.b. Pay particular attention to the square brackets that appear in the above code-sample, vs. your original post.   It does not matter that the word People is or isn’t in-quotes ... what does matter are the square-brackets indicating an array of (in this case) hash-references.

      Perl data structures can become quite intricate because you can certainly have more than one reference to the same hash (or whatever-it-is).   You can do things similar to indexes in an SQL database, quite easily ... effectively, one piece of data is “in more than one place at one time.”   As long as you mind your P’s and Q’s ...

Re: Question regarding hash with multiple values
by 5mi11er (Deacon) on Jul 10, 2013 at 01:24 UTC
    What you're describing is possibly an array of hashes (AoH), or a hash of array of hashes (HoAoH). Read the link the above poster sited for more information about these advanced data structures.

    -Scott

Re: Question regarding hash with multiple values
by BillKSmith (Monsignor) on Jul 10, 2013 at 13:59 UTC
    Here is an AoH solution.
    use strict; use warnings; use Data::Dumper; my %celebs = ( 'Bob Dole' => { 'address' => '123 peach st.', 'spouse' => 'Bill Clinton', 'father' => 'Frank Dole' }, 'Al Pacino' => { 'address' => '123 orange st.', 'spouse' => 'Robert Deniro', 'father' => 'Marlon Brando' } ); my @people = map { { name => $_, address => $celebs{$_}{address}, spouse => $celebs{$_}{spouse}, father => $celebs{$_}{father}, } } keys %celebs; print Data::Dumper->Dump( [\@people],[qw(*people)] );
    OUTPUT:
    @people = ( { 'spouse' => 'Robert Deniro', 'father' => 'Marlon Brando', 'name' => 'Al Pacino', 'address' => '123 orange st.' }, { 'spouse' => 'Bill Clinton', 'father' => 'Frank Dole', 'name' => 'Bob Dole', 'address' => '123 peach st.' } );
    Bill
      I'd apply a small change:
      use strict; use warnings; use Data::Dumper; my %celebs = ( 'Bob Dole' => { 'address' => '123 peach st.', 'spouse' => 'Bill Clinton', 'father' => 'Frank Dole' }, 'Al Pacino' => { 'address' => '123 orange st.', 'spouse' => 'Robert Deniro', 'father' => 'Marlon Brando' } ); my @people = map { { name => $_, %{$celebs{$_}}, # <- Change is here } } keys %celebs; print Data::Dumper->Dump( [\@people],[qw(*people)] );
      So you don't need to "hard code" the celeb's keys.

      s$$([},&%#}/&/]+}%&{})*;#$&&s&&$^X.($'^"%]=\&(|?*{%
      +.+=%;.#_}\&"^"-+%*).}%:##%}={~=~:.")&e&&s""`$''`"e