http://qs1969.pair.com?node_id=191727

gnu@perl has asked for the wisdom of the Perl Monks concerning the following question:

I have the following hash of hashes:
my %switch_hash = ( chrdex => { DEX => { '01-AUG-02' => 1, '03-AUG-02' => 3, } }, uslcgb5e2sm =>{ Greensboro => { '4-AUG-02' => 1, '6-AUG-02' => 2, } }, uslecat25e1 => { 'Atlanta II' => { '1-AUG-02' => 1, '2-AUG-02' => 3, '3-AUG-02' => 1, '4-AUG-02' => .25, } }, ); $rhent = \%switch_hash;
I want to do this:
my @dates = ( keys %{(keys %{(keys %$rhent)})} );
and I get this error:
Can't use string ("3") as a HASH ref while "strict refs" in use at ./x +cl3.pl line 301
Can something like this be done to get the key containing the date from the final hash? NOTE: There is a reason for using a reference, but that is beyond the scope of this question.

Replies are listed 'Best First'.
Re: using 'keys' recursively on a hash of hashes
by Abigail-II (Bishop) on Aug 21, 2002 at 13:48 UTC
    my @keys = map {keys %$_} map {values %$_} values %$rhent;
    Abigail
Re: using 'keys' recursively on a hash of hashes
by fruiture (Curate) on Aug 21, 2002 at 13:51 UTC

    use map and values:

    my @dates = map { keys %$_ } map { values %$_ } values %$rhent;
    --
    http://fruiture.de
Re: using 'keys' recursively on a hash of hashes
by krisahoch (Deacon) on Aug 21, 2002 at 14:21 UTC

    You may also want to think about misplaced commas and quotation marks. I have reformatted your hash to make it easier for me to read (sorry, I have single style dyslexia)

    
    my %switch_hash =
    (
     chrdex   => 
     {
      DEX   => 
      {
       '01-AUG-02'  => 1,
       '03-AUG-02'  => 3,#<-- Do you need this comma?
      }
     },
      
     uslcgb5e2sm => 
     {
      Greensboro  => 
      {
       '4-AUG-02'   => 1,
       '6-AUG-02'   => 2, #<-- Do you need this comma?
      }
     },
      
     uslecat25e1       => 
     {
      'Atlanta II' =>  #<-- Do you need quotation marks here?
      {
       '1-AUG-02'   => 1,
       '2-AUG-02'   => 3,
       '3-AUG-02'   => 1,
       '4-AUG-02'   => .25,  #<-- Do you need this comma?
      }
     }, #<-- Do you need this comma?
    );
    
    

    Kristofer

    Microwaving a Twinkie is a bad idea <T.W.I.N.K.I.E.S Project>

      The extraneous commas are no problem. That is one of the many improvements of Perl versus C. These extra commas allow easier additions to the hash with any of Emacs, Vi, Notepad, Wordpad, Ultra-edit, or even ed.

      Another possible style, which I prefer, consists in writing the comma at the beginning of the next line, not the end of the previous one. Example:

      my %switch_hash =
        (
         chrdex   => 
         {
          DEX   => 
          {
              '01-AUG-02'  => 1
            , '03-AUG-02'  => 3
          }
         }
          
       , uslcgb5e2sm => 
         {
          Greensboro  => 
          {
              '4-AUG-02'   => 1
            , '6-AUG-02'   => 2
          }
         },
          
       , uslecat25e1       => 
         {
          'Atlanta II' =>  # quotation marks are required here
          {
              '1-AUG-02'   => 1
            , '2-AUG-02'   => 3
            , '3-AUG-02'   => 1
            , '4-AUG-02'   => .25
          }
         }
        );
      
      
      This style also allows easier editing of the hash.
        Another possible style, which I prefer, consists in writing the comma at the beginning of the next line, not the end of the previous one.
        That reminds me of the professor who gave us our first programming classes back in university. He would write the semi-colons before the statements, not after them. (This was in Pascal, where semi-colons are statement separators, just like in Perl).
        This style also allows easier editing of the hash.
        Really? How? I see as disadvantage that if you remove the first item you need to modify the next line. Or if you insert an item at the beginning, you need to modify the next line too. The big advantage of putting a comma after the items is that you can always put a comma there, and don't have to do special things when adding or removing elements - not even at the beginning or end.

        Abigail

Re: using 'keys' recursively on a hash of hashes
by physgreg (Scribe) on Aug 21, 2002 at 14:10 UTC
    Try this:
    my @dates = map {keys %{$_}} map {values %{$_}} values %{$rhent};
Re: using 'keys' recursively on a hash of hashes
by gnu@perl (Pilgrim) on Aug 22, 2002 at 20:13 UTC
    Yes, as a few people have pointed out, the 'extra' commas are there for the ease of editing. The main reason is that others may add to or delet from this list and if they just follow the format set out (they might not wholy understand what they are doing) they will be find. The quotes were to guarantee the strings are passed as is, spaces and all.