2010-03-24 4 views
5

Dies ist das erste Mal, dass ich Hashes und Arrays auf diese Weise manipuliert habe - und es funktioniert. Grundsätzlich gibt es für jeden Schlüssel mehrere Werte, die ich aufzeichnen und dann in der Form "Schlüssel -> Wert -> Wert -> Wert ..." ausdrucken möchte.Ist dies der richtige Weg, um einen Perl-Hash zu erstellen, der Arrays verwendet?

Mein Code ist wie folgt. Ich bin überrascht, dass es funktioniert, so besorgt, dass es "aus Versehen" funktioniert. Ist dies der richtige Weg, um diese Aufgabe zu erfüllen, oder gibt es eine effizientere oder geeignete Methode?

while ($source =~ m/(regex)/g) { #Get all key names from source 
    $listkey = $1; #Set current list key to the current regex result. 
    $list{$listkey} = ++$i unless $list{$listkey}; #Add the key to the hash unless it already exists. 
    $list{$listkey} = [] unless exists $list{$listkey}; #Add an array for the hash unless the hash already exists. 
    while ($loopcount==0) { 
      if ($ifcount==0) { 
        $listvalue=result_of_some_function_using_list_key; #Get the first list value by using the list key. 
        $ifcount++; #Increment so we only get the first list value once. 
      } else { 
        $listvalue=result_of_some_function_using_list_value; #Update the list value by using the last list value. 
      } 
      if ($listvalue) { #If the function returned a value... 
        push @{$list{$listkey}}, $listvalue; #...then add the value to the hash array for the key. 
      } else { #There are no more values and we need a new key. 
        $listkey=0; #Reset variable. 
        $listvalue=0; #Reset variable. 
        $loopcount++; #Increment loop counter to exit loop. 
      } 
    } 
$ifcount=0; #Reset count variable so the next listvalue can be generated from the new key. 
    $loopcount=0; #Reset count variable so another loop can begin for a new key. 
} 
foreach $listkey (keys %list) { #For each key in the hash. 
    print "$listkey --> "; #Print the key. 
    @values = @{$list{$listkey}}; #Reference the arrays of the hash. 
    print join ' --> ', @values; #Print the values. 
    print "\n"; #Print new line. 
} 
+7

Sie sollten wirklich in Gebrauch streng sein; Verwenden Sie Warnungen; 'Modus – Zaid

+0

Autsch, dass eine böse Liste der Warnungen produziert. Ich werde sie durchgehen müssen. – Structure

+4

Ich hoffe, dass der echte Code nicht so viele Kommentare hat. –

Antwort

2

Der folgende Code das gleiche wie Ihr Code tut, ohne die unnötigen Schritte.

while ($source =~ m/(regex)/g) { # Get all key names from source 
    $listkey = $1;   # Grab current regex result. 
    $listvalue = result_of_some_function_using_list_key; 
    while ($listvalue) { 
     push @{$list{$listkey}}, $listvalue; 
     $listvalue = result_of_some_function_using_list_value; 
    } 
    $listkey = 0;    # Reset variable. 
    $domain = 0;     # Reset variable. 
} 

Wie jedoch andere kommentiert haben, sollten globale Variablen in den meisten Fällen vermieden werden. Stattdessen sollten der Listenschlüssel und der Listenwert lexikalisch mit my() definiert sein, und die Funktionen zum Generieren von Listenwerten sollten einen oder mehrere Parameter (Domäne, Listenschlüssel und/oder Listenwert) als Eingabe verwenden.

Die Linien

$list{$listkey} = ++$i unless $list{$listkey}; 
$list{$listkey} = [] unless exists $list{$listkey}; 

in Ihrem ursprünglichen Code nicht benötigt wird, ist es mit push @{ $list{$key} }, $value ausreicht, um einen Eintrag zu initialisieren.

+0

Danke, ich verstehe besser, wo ich nach der kurzen Erklärung falsch gelaufen bin. – Structure

1

Nein! Wenn das funktioniert, ist es definitiv "aus Versehen". Aber es ist auch offensichtlich, dass dies nicht dein wirklicher Code ist und dass du mehrere Fehler hinzugefügt hast, um es zu einem Beispiel zu "übersetzen". Es ist schwer zu beurteilen, was genau deine Absicht war, aber es geht vom Skelett deines Programms aus wie es sollte etwas wie sein:

my %result; 

while ($source =~ m/(regex)/g) { 
    my $key = $1; 
    my $value = mangle($key); 
    while ($value) { 
    push @{ $results{$key} }, $value; 
    $value = frob($value); 
    } 
} 

und nicht mehr. Ihre Versuche, den Hash zu initialisieren, tun nicht, was Sie denken, sie sind (und sind nicht notwendig), Ihre while-Schleife, wie geschrieben, ist überhaupt keine gute Idee, und auch nicht alle globalen Variablen.

2

Der obige Code enthält viele unnötige Schritte. Perl ist eine sehr ausdrucksvolle Sprache und ermöglicht Logik wie diese sehr einfach ausgedrückt werden:

# uncomment for some sample data 
# sub function {"@_" !~ /^\[{3}/ and "[@_]"} 
# my $source = 'one two three'; 

my %list; 
while ($source =~ m/(\S+)/g) { 
    my $key = $1; 
    my $value = function($key); 

    while ($value) { 
     push @{ $list{$key} }, $value; 
     $value = function($value) 
    } 
} 

for my $key (keys %list) { 
    print join(' --> ' => $key, @{$list{$key}}), "\n"; 
} 
+0

vereinbart. Im Allgemeinen sollten Sie in Perl nur Schleifenindizes sehen (das 'for ($ i = 0 ...' C-style loop) oder counters in Fällen, in denen Sie tatsächlich etwas mit diesen Werten machen müssen. counters und indexes sind auch oft eine gute Quelle für peinliche Fehler – plusplus

Verwandte Themen