Dear Monks,
I am stuck with creating a multi-level hash and look forward for some help from the community.
I have to create a cgi that reads a data file, displays the hierarchy in a windows explorer format and then allows the user to execute some program based on the selection.
I found that I can use the CGI-Explorer module in CPAN to create a windows explorer type interface. To achieve that, I need to create a multi-level hash data structure from the data file.
Now, my data file looks as follows:-
[Add Menu] Name = L1A Title = L1A [Done] [Add Entry] Action = None Text = L2A [Done] [Add Entry] Action = None Text = Second [Done] ----------------------- [Add Menu] Name = L2A Title = L1A - L2A [Done] [Add Entry] Action = None Text = L3A [Done] [Add Entry] Action = None Text = L3B [Done] ------------------------- [Add Menu] Name = Second Title = L1A - Second [Done] [Add Entry] Action = exe command Text = Third1 [Done] [Add Entry] Action = exe command Text = L3B [Done] ------------------------- [Add Menu] Name = L3A Title = L1A - L2A - L3A [Done] [Add Entry] Action = exe command Text = L4A [Done] [Add Entry] Action = exe command Text = L3B1 [Done] ------------------------- [Add Menu] Name = L3B Title = L1A - L2A - L3B [Done] [Add Entry] Action = exe command Text = L4A [Done] ------------------------- etc.. etc..
and I need to create a mutli-hash structure as shown below from the data file:-
$VAR1 = { 'L1A' => { 'L2A' => { 'L3A' => { 'L4A' => 'exe command', 'L3B1' => 'exe command' }, 'L3B' => { 'L4A' => 'exe command' } }, 'Second' => { 'L3B' => 'exe command', 'Third1' => 'exe command' } } };
So, I decided to read the data file, create an 'array of hashes' that would combine both the 'Add Menu' and the corresponding 'Add Entry', which would look as follows:-
$VAR1 = [ { 'Counter' => 1, 'Action' => 'None', 'Name' => 'L1A', 'Text' => 'L2A', 'Title' => 'L1A' }, { 'Counter' => 2, 'Action' => 'None', 'Name' => 'L1A', 'Text' => 'Second', 'Title' => 'L1A' }, { 'Counter' => 3, 'Action' => 'None', 'Name' => 'L2A', 'Text' => 'L3A', 'Title' => 'L1A - L2A' }, { 'Counter' => 4, 'Action' => 'None', 'Name' => 'L2A', 'Text' => 'L3B', 'Title' => 'L1A - L2A' }, { 'Counter' => 5, 'Action' => 'exe command', 'Name' => 'Second', 'Text' => 'Third1', 'Title' => 'L1A - Second' }, { 'Counter' => 6, 'Action' => 'exe command', 'Name' => 'Second', 'Text' => 'L3B', 'Title' => 'L1A - Second' }, { 'Counter' => 7, 'Action' => 'exe command', 'Name' => 'L3A', 'Text' => 'L4A', 'Title' => 'L1A - L2A - L3A' }, { 'Counter' => 8, 'Action' => 'exe command', 'Name' => 'L3A', 'Text' => 'L3B1', 'Title' => 'L1A - L2A - L3A' }, { 'Counter' => 9, 'Action' => 'exe command', 'Name' => 'L3B', 'Text' => 'L4A', 'Title' => 'L1A - L2A - L3B' } ];
Then, I wanted to go over each array element, get the 'Title' and split that using the '-'(hypen) separator, and build the multi-hash. For example, the first entry in the mutli-hash would be
$Menu_Multi_Hash{'L1A'}{'L2A'} = 'none'; etc.. etc.. and for the last one, it will be $Menu_Multi_Hash{'L1A'}{'L2A'}{'L3B'}{'L4A'} = 'exe command'; (please note that the first three elements are the ones arrived by spl +itting the 'Title', the fourth is the 'Text' and the right hand side +is the 'Action')
The problem is that I am not able write a generic subroutine that can take the 'Title', 'Text' and 'Action' and build the multi-hash, because the 'Title' can have anywhere from one element to ten.
I am not sure if this is a good approach. Any advice would be of great help.. Thanks..
Below is the code is for creating the array of hashes from the data file.
use Data::Dumper; use strict; open (FILE, "filename"); my $menu_counter = 0; my $MenuName; my $MenuTitle; my %temp_hash; my $line_read; my @MenuList; #Array of Hashes while (<FILE>) { next if /^\s*$/; if ( /^\[Add Menu]/../^\[Done]/) { $line_read = $_; if ( $line_read=~/^\s*(\w+)\s=\s(.*)/ ) { if ($1 eq "Name") { $MenuName = $2; } elsif ($1 eq "Title") { $MenuTitle = $2; } } } elsif ( /^\[Add Entry]/../^\[Done]/) { $line_read = $_; if ( $line_read=~/^\s*(\w+)\s=\s(.*)/ ) { if ( $1 eq "Action") { if ($menu_counter != 0) { push @MenuList, {%temp_hash}; } $menu_counter++; %temp_hash = &initialize_structure( $1, $2, $menu_coun +ter, $MenuName, $MenuTitle ); } else { &createpair( $1, $2); } } } } push @MenuList, {%temp_hash}; print Dumper(\@MenuList); sub initialize_structure() { my ( $key, $value, $counter, $menuname, $menutitle) = @_; my %temp_var; %temp_var = ( Name => "", Title => "", Action => "", Text => "", Counter => "", ); $temp_var{$key} = $value; $temp_var{'Counter'} = $counter; $temp_var{'Name'} = $menuname; $temp_var{'Title'} = $menutitle; return %temp_var; }; # subroutine to populate rest of the data structure sub createpair() { my($key, $value) = @_; $temp_hash{$key} = $value; };
In reply to Stuck with Creating Multi-Level hash by sara2005
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |