Hashes of Arrays
plmc
created: 2006-06-05 16:19:56
I've having difficulty with a hash of arrays. I'm creating a dropdown menu system with headers a b .. z under each letter is are menuItems beginning with a b .. z. my structure looks like this;
       my @menu_bar_names = qw ( aMenu bMenu ... );
       my @MenuItems="";
       my %aMenu = { label => "  A",
                     MenuItems => [ @MenuItems ] };
       my %bMenu = { label => "  B",
                     MenuItems => [ @MenuItems ] };
       my %cMenu = { label => "  C",
                      MenuItems => [ @MenuItems ] };
I used the following to populate each MenuItem array.
   foreach my $app (@sorted_applications) {
      $app = lc $app;
      if ( "$app" lt "b" ) {
         push  ( @{ $aMenu{MenuItems} }, $app);
         next;
      } elsif ($app lt "c" ) {
         push  (@{ $bMenu{MenuItems} },$app);
         next;
...
And the following to print the first element.
         print " @{$aMenu{MenuItems}}[0]\n";
I would like to avoid using $aMenu in the printing and use something like, $abc_menu instead of hard coding $aMenu, $bMenu such as;
foreach my $abc_menu (@menu_bar_names) {
         print " @{$abc_menu{MenuItems}}[0]\n";
}
but I get the following error. 'Global symbol "abc_menu"; requires explicit package name at...' The error makes sense and I understand why I get it. But I haven't figured out how to get around it. I'm sure it's something simple but I've read so much I've confused myself. Thanks for taking the time to read this.
Re: Hashes of Arrays
created: 2006-06-05 16:36:32
I would trade in the three menu declarations for one with an extra hash level keyed by app name (or actually by lc $app):
my %Menu = {
  app1 => {
         label => "  A",
         MenuItems => [ @MenuItems ]
       },
  app2 => {
         label => "  B",
         MenuItems => [ @MenuItems ]
       },
  app3 => {
         label => "  C",
         MenuItems => [ @MenuItems ]
  },
};
Then replace other mentions of aMenu, etc. with Menu{lc_app}. For example:
foreach my $app (@sorted_applications) {
      $app = lc $app;
      push @{ $Menu{$app}{MenuItems} }, $app;
}
Phil
Re: Hashes of Arrays
created: 2006-06-05 16:43:07
Be sure to always use strict; and use warnings; ... for example this line is incorrect:
my %aMenu = { label => "  A", MenuItems => [ @MenuItems ] };
And should be (warnings would have complained about it):
my %aMenu = ( label => "  A", MenuItems => [ @MenuItems ] );

As for your root issue, I think you're just looking for another level of hashing ..
# if  @MenuItems actually has something it it, then   MenuItems => [@MenuItems]   is fine
# but for simplicity i just made it MenuItems => []
my %menus = ( a => { label => "  A", MenuItems => [] },
              a => { label => "  A", MenuItems => [] },
              a => { label => "  A", MenuItems => [] },
);
#OR:  my %menus = map { lc($_) => {label => "  $_", MenuItems => []} } 'A' .. 'C';

# then:
foreach my $app (map {lc $_} @sorted_applications) {
  push @{ $menus{$app}->{MenuItems} }, $app;
}
Re: Hashes of Arrays
created: 2006-06-05 16:55:53

Use the menu letter as the key and defer creation of hash entries until they are needed cleans things up a little. Consider:

use strict;
use warnings;

my %menus;
my @sorted_applications = qw(app1 App2 bapp bopp cap cop);

for my $app (@sorted_applications) {
    # Create and populate menus
    $app = lc $app;
    
    my $letter = substr $app, 0, 1;
    
    if (! exists $menus{$letter}) {
        #create the menu entry
        $menus{$letter}{label} = '$nbsp; ' . uc $letter;
        $menus{$letter}{items} = []; # Not required, but shows intent
    }
    
    push @{$menus{$letter}{items}}, $app;
}

# Dump the menu structure
for my $topMenu (sort keys %menus) {
    print "$menus{$topMenu}{label}\n";
    print "   $_\n" for @{$menus{$topMenu}{items}};
}

Prints:

$nbsp; A
   app1
   app2
$nbsp; B
   bapp
   bopp
$nbsp; C
   cap
   cop

DWIM is Perl's answer to Gödel
Re^2: Hashes of Arrays
created: 2006-06-06 09:11:59
Thanks for the suggestions I will test them today.

perlmonks.org content © perlmonks.org and davidrw, GrandFather, philcrow, plmc

prlmnks.org © 2006 edmund von der burg (eccles & toad)

v 0.03