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

Hello,

I already got help in the chatterbox. But now I don't know how to solve the following problem.

I have a hash with for example the following input:

$VAR1 = { 'File_Handler' => { 'Compile_File' => undef, 'Log_Details' => undef, 'Complete_Logging' => undef, 'Get_Config' => undef, 'Get_Data' => undef, 'Get_Abc_Data' => undef, 'Internal_Operations' => { 'Get_Abc_Data' => + undef, 'Start_Operations +' => undef, 'Get_Start_Up_Dat +a' => undef, 'Construct_Failur +e_Ident' => undef, 'Construct_Additi +onal_Words' => undef, }, 'Start_File_Handler' => undef } };

My goal is it to replace all undef with the lines of code in a file.

My problem is how to get the files out of this hash. The first file name would be: "File_Handler.Compile_File.2.ada". The second file name is "File_Handler.Log_Details.2.ada". Another file name would be "File_Handler.Internal_Operations.Get_Abc_Data". You see the file name consists of the keys separated by a "." and has the suffix ".2.ada.".

The hash can also have much more than only 3 levels.

Thank you for your help.

Greetings,

Dirk

Replies are listed 'Best First'.
Re: Filling value of nested hash
by kennethk (Abbot) on Dec 09, 2010 at 16:29 UTC
    First, keep in mind that since this is a hash, order is arbtrary so there is no "first" file name. If order matters, you should be using an array of arrays rather than a hash of hashes.

    Since you are dealing with an object of unknown depth, a recursive parser is likely easiest. Maybe something like

    #!/usr/bin/perl use strict; use warnings; my $VAR1 = { 'File_Handler' => { 'Compile_File' => undef, 'Log_Details' => undef, 'Complete_Logging' => undef, 'Get_Config' => undef, 'Get_Data' => undef, 'Get_Abc_Data' => undef, 'Internal_Operations' => { 'Get_Abc_Data' => + undef, 'Start_Operations +' => undef, 'Get_Start_Up_Dat +a' => undef, 'Construct_Failur +e_Ident' => undef, 'Construct_Additi +onal_Words' => undef, }, 'Start_File_Handler' => undef } }; sub output_files { my $path = shift; my %hash = @_; for my $key (keys %hash) { if (ref $hash{$key}) { output_files("$path.$key",%{$hash{$key}}); } else { print "$path.$key.2.ada\n" } } } while (my($key, $value) = each %$VAR1) { output_files($key, %$value); }
      You can factor out the recursion with Data::Walker or Data::Leaf::Walker :
      use strict; use warnings; use Data::Leaf::Walker; my %data = ( File_Handler => { Compile_File => undef, Log_Details => undef, Complete_Logging => undef, Get_Config => undef, Get_Data => undef, Get_Abc_Data => undef, Start_File_Handler => undef, Internal_Operations => { Get_Abc_Data => undef, Start_Operations => undef, Get_Start_Up_Data => undef, Construct_Failure_Ident => undef, Construct_Additional_Words => undef, }, }, ); my $walker = Data::Leaf::Walker->new( \%data ); while ( my ( $k, $v ) = $walker->each ) { my $filename = join '.', @{$k}, '2.ada'; print $filename, "\n"; }
Re: Filling value of nested hash
by PeterPeiGuo (Hermit) on Dec 09, 2010 at 16:31 UTC

    Traverse the tree, for each node, if its value is undef, deal with the file etc, otherwise, go to the next level. It can be written in a recursive way.

    Peter (Guo) Pei