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

Hi all, I've a problem with a script done by myself that I need to transform in a parametrical solution. My scrypt interact with an ADABAS db launching command to manage fields. Originally I wrote a static solution that work but it's not my target. In ADABAS fields are ohisically named as 2 char ( AA,AB,DC,DE etc.). This scripts extract from a shell command a sorted fields list of a $file in a $Database given from user, then finds the next available field.

use strict; my $file = ""; my $Database = ""; print "Inserire il Numero del file da analizzare: "; $file = <>; chomp $file; print "\n"; print "Inserire il Numero del Database su quale si vuole fare l'analis +i: "; $Database = <>; chomp $Database; print "\n"; my $cmd1 = "adarep db=$Database fdt file=$file "; my @ElencoDati = `$cmd1 |grep " 1 I "`; push (@ElencoDati, `$cmd1 |grep "SUPER"`); my $ClearScr = `clear`; my @array1 = ""; my @ElencoCampi = ""; foreach (@ElencoDati) { @array1 = split /\s+/, $_; push (@ElencoCampi, $array1[3]); } my @ElencoCampiOrdinati = sort @ElencoCampi; # SORTED ARRAY OF FIELDS print "\n Elenco Campi Assegnati sul file $file del DB $Database Ordin +ati \n"; foreach (@ElencoCampiOrdinati) { print "$_\n"; } print "\nL'ultimo campo utilizzato sul file $file del database $Databa +se e: ", $ElencoCampiOrdinati[$#ElencoCampiOrdinati],"\n\n\n"; my $UltimoCampo = $ElencoCampiOrdinati[$#ElencoCampiOrdinati]; chomp $UltimoCampo; my @Caratteri = split (//,$UltimoCampo); print "\n"; my $PrimaLettera = ord $Caratteri[0]; print "Il valore numerico nella tabella ASCII della prima lettera e: $ +PrimaLettera\n\n"; my $SecondaLettera = ord $Caratteri[1]; print "Il valore numerico nella tabella ASCII della seconda lettera e: + $SecondaLettera\n\n"; if ( $SecondaLettera < 90 ) { $SecondaLettera+=1; my $ProssimoCampo = chr ($PrimaLettera).chr($SecondaLettera); print "\n\nIl prossimo campo disponibile e: $ProssimoCampo\n\n"; # THI +S IS NEXT AVAILABLE FIELD } if ( $SecondaLettera == 90 ) { $PrimaLettera+=1; $SecondaLettera=65; my $ProssimoCampo = chr ($PrimaLettera).chr($SecondaLettera); print "\n\nIl prossimo campo disponibile e: $ProssimoCampo\n\n"; } #END

PROBLEM GOING ON NEXT STEP I need to automatically define the environment taken from server hostname and generate automatically the same result for any $Database of the server for a user given $file. so I've established the environment:

my $hostname = `hostname`; my $Environment; my @Databases; my $AdabasScriptDir; my $AdabasProductionScript; if ( $hostname =~ /itrmsl12/ ) { $Environment = "SVILUPPO"; @Databases = ("5","6"); $AdabasScriptDir = "/opt/app1vg/appl/script/Utility/sag/adabas/"; } if ( $hostname =~ /itrmcl01/ ) { $Environment = "COLLAUDO"; @Databases = ("2","27","37"); $AdabasScriptDir = "/opt/app1vg/appl/script/Utility/sag/adabas/"; }

...now I would like to make a sub(@Databases) that give a separate Array of result... the question is in which way? My idea is to obtain something like:

%Databases ( "2" => (@ElencoCampiOrdinati), ($ProssimoCampo) "27" => (@ElencoCampiOrdinati), ($ProssimoCampo) "37" => (@ElencoCampiOrdinati), ($ProssimoCampo) )

...could someone explain to me how could I proceed?

Replies are listed 'Best First'.
Re: Hash of Arrays or Arrays of arrays? and how proceed?
by jethro (Monsignor) on Jul 29, 2011 at 13:47 UTC

    I'm not quite clear on what you are asking. What parameters do you want to give to the subroutine and what data do you want back? If the question is whether to use HashOfArrays or ArraysOfArrays, a simplicistic answer would be: If you need an ordering or you want to access the data by number, use an array. In most other cases a hash is the right answer.

    You seem to want to store an array and a scalar as data. In that case an array as secondary datastructure makes sense, just put the scalar as the first (or last item) into the array. Consequently you can identify it through it being the first (or last) item of the array

    You can find lots of examples how a HashOfArrays is accessed in perllol

    One other point, the lines where you calculate the successor of a two-character string should be extracted into a subroutine. That would make your script more readable and the algorithm itself better interchangeable and testable

      Thank you very much jethro! I'll search better on the example, even if for me it's difficult convert the fixed examples (@array 1,2,3,red) with the parametrical solution.

      Answering to your first question I would like to pass to the subroutine only the @Databeses array obtained in the Environment defined section and the Table ($file) in which i would like to obtain results. The subroutine (as first instance) have to give me (for every Database of the environment) an array of ordered fields, and a scalar conteining the next available field. I've thinked to an hash but I've not understand how could I pass to the hash the @Database and how I could populate it with the Array that I obtain

      For the second suggestion thanks very much also if I'm a beginner I would like to point directly to the best possible solution.

        I'll try to give you a skeleton of that subroutine:

        sub ExtractDatabaseFields { my $file= shift; my @databases= @_; my %result; foreach my $database (@databases) { my @fields= ... #extract data from database my $nextfield= .... #find next field $result{$database}{next}= $nextfield; $result{$database}{fields}= \@fields; } return \%result; } #------------------- # Accessing my $result= ExtractDatabaseFields($file,@databases); #print next available field of database 27: print $result->{"27"}{next}; #extract the fourth field from database 27: my $field3= $result->{"27"}{fields}[3]; #add another field to database 27: push @{$result->{"27"}{fields}}, "whatever"; #loop over the fields of database $x: foreach $field ( @{$result->{$x}{fields}} ) { .... }

        The resulting data structure would be a HashOfHashOfArrays, not a HashofArrays, but this makes the access to the data much clearer. If this isn't what you wanted you might give a more elaborate example