3 Stimmen

Speichern mehrerer Werte in einem Schlüssel in einem Hash of Hash mit Perl

Ich versuche, eine Datenstruktur zum Speichern von Daten zu erstellen, die ich aus einer Datenbank entnehme:

$Interaction{$TrGene}={
CisGene => $CisGene,
E => $e,
Q => $q,};

Ein einzelnes $TrGen ist mit einer Reihe von CisGenen verbunden (die ein eindeutiges E &Q haben). z.B:

TrGene1 CisGene1 Q1 E2

TrGene1 CisGene2 Q2 E3

Das letzte TrGene1 überschreibt die vorangegangenen. Ich denke, dass ich einen Verweis auf ein Array erstellen muss, aber ich verstehe nicht ganz, wie dies nach dem Lesen dieser Webseite geschehen soll: http://perldoc.perl.org/perlreftut.html

Ich habe versucht, das Land/Stadt-Beispiel auf dieser Webseite zu verwenden, war aber nicht sehr erfolgreich:

$Interaction{$TrGene}={
CisGene => $CisGene,
E => $e,
Q => $q,};
push @{$Interaction{$TrGene}}, $CisGene;

Ich erhalte die Fehlermeldung 'Not an ARRAY ref'. Ich habe auch nur $CisGene dort verwendet, aber es muss nicht überschreiben die E & Q-Werte für diese CisGene. (so wird dieser Hash wissen, dass die CisGene zu einem bestimmten E und Q zugeordnet ist, oder muss ich eine andere Schicht von Hash für das erstellen?)

Gracias

3voto

TLP Punkte 65295

Ihr Code, aber richtig eingerückt, damit er lesbar ist.

$Interaction{$TrGene} = {
    CisGene => $CisGene,
    E       => $e,
    Q       => $q,
};
push @{$Interaction{$TrGene}}, $CisGene;

Code erklärt:

Sie weisen eine Liste von Schlüssel-Wert-Paaren einem anonymen Hash zu, indem Sie geschweifte Klammern verwenden {} und weisen Sie diese Hash-Referenz dem $TrGene Taste in der %Interaction Haschisch. Dann versuchen Sie, diesen Wert als Array-Referenz zu verwenden, indem Sie ihn mit @{ ... } was nicht funktioniert.

Wenn Sie einen Hash-Schlüssel mit anderen Werten eingeben, werden diese überschrieben. Nehmen wir einige praktische Beispiele, es ist wirklich ziemlich einfach.

$Interaction{'foobar'} = {
    CisGene => 'Secret code',
    E       => 'xxx',
    Q       => 'yyy',
};

Jetzt haben Sie eine Hash-Referenz unter dem Schlüssel 'foobar' . Dieser Hash ist eigentlich ein frei stehender Verweis auf eine Datenstruktur. Ich denke, es ist einfacher, den Überblick über Strukturen zu behalten, wenn man sie sich als Skalare vorstellt: Ein Hash (oder Array) kann immer nur Skalare enthalten.

Die Raute %Interaction kann eine Reihe von Schlüsseln enthalten, und wenn Sie Daten wie oben eingegeben haben, werden alle Werte Hash-Referenzen sein. z.B.:

$hash1 = {  # note: curly brackets denote an anonymous hash 
    CisGene => 'Secret code',
    E       => 'xxx',
    Q       => 'yyy',
};
$hash2 = {
    CisGene => 'some other value',
    E       => 'foo',
    Q       => 'bar',
};

%Interaction = ( # note: regular parenthesis denote a list
    'foobar'   => $hash1,  # e.g. CisGene => 'Secret code', ... etc. from above
    'barbar'   => $hash2   # e.g. other key value pairs surrounded by {}
    ...
);

Der Typ des Wertes, der in $hash1 y $hash2 ist jetzt ein Verweis, eine Adresse auf Daten im Speicher. Wenn Sie sie ausdrucken print $hash1 werden Sie etwas sehen wie HASH(0x398a64) .

Wenn Sie nun einen neuen Wert in %Interaction Wenn Sie einen bestehenden Schlüssel verwenden, wird dieser Schlüssel überschrieben. Denn ein Hash-Schlüssel kann immer nur einen Wert enthalten: Einen Skalar. In unserem Fall ein Verweis auf einen Hash.

Was Sie in Ihrem Beispiel versuchen, ist die Verwendung des Wertes der Option 'foobar' Schlüssel als Array-Referenz (was dumm ist, denn wie Sie jetzt oben sehen können, ist es eine Hash-Referenz):

push @{$Interaction{$TrGene}}, $CisGene;

Umgeschrieben:

push @{  $hash1  }, 'Secret code';  # using the sample values from above

Nein... das funktioniert nicht.

Was Sie brauchen, ist ein neuer Container. Wir machen den Wert des Schlüssels 'foobar' eine Array-Referenz stattdessen:

%Interaction = (
    'foobar'   => $array1,
    ...
);

どこで

$array1 = [ $hash1, $hash2 ];

oder

$array1 = [       # note the square brackets to create anonymous array
              {   # curly brackets for anonymous hash
                  CisGene => 'Secret code',
                  E       => 'xxx',
                  Q       => 'yyy',
              },  # comma sign to separate array elements
              {   # start a new hash
                  CisGene => 'Some other value',
                  E       => 'foo',
                  Q       => 'bar',
              }   # end 
           ];     # end of $array1

Das ist jetzt alles etwas umständlich formuliert, also machen wir es einfacher:

$CisGene = 'foobar';
$e = 'xxx';
$q = 'yyy';

my $hash1 = {
        CisGene => $CisGene,
        E       => $e,
        Q       => $q,
};

push @{$Interaction{$TrGene}}, $hash1;

Oder Sie können die Variable temp weglassen $hash1 und ordnen Sie es direkt zu:

push @{$Interaction{$TrGene}}, {
    CisGene => $CisGene,
    E       => $e,
    Q       => $q,
};

Und beim Zugriff auf die Elemente:

for my $key (keys %Interaction) {  # lists the $TrGene keys 
    my $aref = $Interaction{$key}; # the array reference
    for my $hashref (@$aref) {     # extract hash references, e.g. $hash1
        my $CisGene = $hashref->{'CisGene'};
        my $e       = $hashref->{'E'};
        my $q       = $hashref->{'Q'};
    }
}

Beachten Sie die Verwendung des Pfeiloperators, wenn Sie direkt mit Referenzen arbeiten. Sie können auch sagen $$hashref{'CisGene'} .

Oder direkt:

my $CisGene = $Interaction{'foobar'}[0]{'CisGene'};

Ich empfehle die Lektüre perldata . Ein sehr praktisches Modul ist Daten::Dumper . Wenn Sie das tun:

use Data::Dumper;
print Dumper \%Interaction; # note the backslash, Dumper wants references

Es druckt Ihre Datenstruktur für Sie aus, was es sehr einfach macht, zu sehen, was Sie tun. Achten Sie auf die Verwendung von Klammern und geschweiften Klammern zur Kennzeichnung von Arrays und Hashes.

2voto

Axeman Punkte 29362

Etwas wie

push @{ $Interaction{ $TrGene }{members} }, $CisGene;

sollte funktionieren.

$Interaction{$TrGene} kann kein Array-Verweis sein, da Sie ihm gerade einen Hash-Verweis zugewiesen haben.

Natürlich sollten Sie vor der Zuweisung prüfen, ob Sie eine Kombination aus E y Q (Ich gehe davon aus, dass es in der $TrGene Taste, sonst verursachen Sie wahrscheinlich noch mehr Chaos. ), werden Sie etwas mehr wie diese wollen:

 $Interaction{ $TrGene } //= { E => $e, Q => $q };
 push @{ $Interaction{ $TrGene }{CisGenes} }, $CisGene;

Auf diese Weise können E y Q sind abhängig von dem Wert von $TrGene erhalten Sie die gewünschten Gruppierungen. Andernfalls können Sie sie wie folgt subscriptieren:

push @{ $Interaction{ $e }{ $q } }, $CisGene;

und erhalten eine Zuordnung mit einer größeren Assoziation zwischen E , Q y $CisGene .

2voto

stevenl Punkte 6696

Du hattest es fast, als du versucht hast, in ein Arrayref zu stoßen. Das Problem war, dass Sie bereits einen hashref zugewiesen haben $Interaction[$TrGene} und versuchte dann, es als Arrayref zu verwenden mit @{ $Interaction{$TrGene} } .

@{ $Interaction{$TrGene} } bedeutet:

  • Sie nehmen den Hash-Wert $Interaction{$TrGene}
  • die Sie dann in ein Array dereferenzieren @{ ... } . Sie können z. B. Folgendes tun: @array = @{$Interaction{$TrGene}} .
  • Wenn es keinen Wert gab in $Interaction{$TrGene} dann wird die Arrayref automatisch an diesem Punkt erstellt (bekannt als Auto-Vivication).

Angenommen, Sie haben diese Hash-Refs erstellt:

my $CisGene1 = {
    CisGene => 'CisGene1',
    E => 'E1',
    Q => 'Q1',
};
my $CisGene2 = {
    CisGene => 'CisGene2',
    E => 'E3',
    Q => 'Q2',
};

Sie können jeden von ihnen in Ihr Arrayref einfügen:

push @{ $Interaction{$TrGene} }, $CisGene1, $CisGene2;

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X