2011-10-26 10 views
5

Ho un problema in cui coppie di numeri si associano ad altre coppie di numeri. Ad esempio, (1,2) -> (12,97). Alcune coppie possono associarsi a più coppie, quindi quello di cui ho veramente bisogno è la possibilità di mappare una coppia in una lista di liste, come (1,2) -> ((12,97), (4,1)). Alla fine del giorno voglio elaborare separatamente ciascuno dei valori (cioè ogni elenco di liste).Perl hash quando sia le chiavi che i valori sono riferimenti di matrice

In Python, ho potuto fare questo semplicemente dicendo:

key = (x, y) 
val = [ a, b ] 
if (x,y) not in my_dict: 
    my_dict[ (x,y) ] = [] 
my_dict[ (x,y) ].append([a,b]) 

Tuttavia, in Perl, devo usare arbitri per le chiavi e valori. Quindi posso sicuramente dire:

$keyref = [ x1, y1 ] 
$valref = [ a, b ] 
%my_hash = { $keyref => $valref } 

Ma cosa succede quando arriva un'altra coppia (x2, y2)? Anche se x2 == x1 e y2 == y1, $ keyref = [x2, y2] sarà diverso dal precedente keyref generato, quindi non vedo un modo per fare la ricerca. Certo, potrei confrontare (x2, y2) con ogni chiave hash dereferenziata, ma dopotutto, Dio ci ha dato delle tabelle hash proprio per evitare la necessità di farlo.

Esiste una soluzione Perl?

Grazie,

-W.

+0

Non è possibile utilizzare un riferimento come chiave. (almeno no senza usare un hash * legato *) –

risposta

0

ho finito per usare la soluzione di Socket Puppet (in la forma dell'opzione 3 di Michael Carmen). Cordiali saluti, ecco un piccolo script Perl che svolge tutte le operazioni di cui ho bisogno nella mia app.

Linee stampate 2:, 3: e 4:, 5: basta usare la sintassi diversa per fare la stessa cosa, e le linee 0: e 1: erano solo intese come controlli di sanità lungo il percorso.

Ciò che questo aggiunge alla soluzione suggerita è l'uso di una matrice di matrici come valore che accompagna una chiave.

@k1 = (12, 13); 
$aref = [ 11, 22 ]; 
$bref = [ 33, 44 ]; 
%h = {}; 
if(not exists $h{$k1[0]}{$k1[1]}) { 
    print "initializing\n"; 
    $h{$k1[0]}{$k1[1]} = []; 
} 
push @{$h{$k1[0]}{$k1[1]}}, $aref; 
push @{$h{$k1[0]}{$k1[1]}}, $bref; 
print "0: ", join ':', @{$h{$k1[0]}{$k1[1]}}, "\n"; 
print "1: ", join ':', ${$h{$k1[0]}{$k1[1]}}[0], "\n"; 
print "2: ", join ':', @{${$h{$k1[0]}{$k1[1]}}[0]}, "\n"; 
print "3: ", join ':', @{${$h{$k1[0]}{$k1[1]}}[1]}, "\n"; 
print "4: ", join ':', @{$h{$k1[0]}{$k1[1]}->[0]}, "\n"; 
print "5: ", join ':', @{$h{$k1[0]}{$k1[1]}->[1]}, "\n"; 

P.S. Avrei aggiunto questo come commento ma era troppo lungo, e ho pensato che fosse logico includere un esempio funzionante.

+0

Congratulazioni per la soluzione. Quando sei in grado, assicurati di contrassegnare la tua risposta come "accettata" in modo che altri possano imparare dal tuo successo. Acclamazioni ~ –

10

In Perl, tutte le chiavi di hash sono stringhe o "stringificate" prima della ricerca. L'utilizzo di un riferimento di matrice come chiave è solitamente l'approccio sbagliato.

E che dire dell'utilizzo di un hash "bidimensionale"?

$hash{$x1}{$y1} = [ $a, $b ]; 
# or 
%hash = ($x1 => { $y1 => [ $a, $b ] }); 


($x2,$y2)=($x1,$y1); 
print @{$hash{$x2}{$y2}}; # will print $a and $b 
+0

Brillante! Grazie. – wchlm

2

Come la maggior parte delle cose in Perl, TMTOWTDI.

Opzione 1: Utilizzare l'emulazione array multidimensionale

$hash{$x,$y} = [$a, $b]; 

Vedere anche la documentazione per il built-in variabili $;.

Opzione 2: Utilizzare il modulo Hash::MultiKey

tie %hash, 'Hash::MultiKey'; 
$hash{[$x, $y]} = [$a, $b]; 

Opzione 3: utilizzare un HoH (hash di hash), invece

$hash{$x}{$y} = [$a, $b]; 
+0

Ho finito per usare la soluzione di Socket Puppet (nella forma dell'opzione 3). Cordiali saluti, ecco un piccolo script Perl che esegue tutte le operazioni che devo fare nella mia app. Linee stampate 2:, 3: e 4:, 5: basta usare una sintassi diversa per fare le stesse cose, e 0: e 1: erano solo intese come controlli di sanità mentale lungo il percorso. L'unica cosa che aggiunge a questi esempi è l'uso di una matrice di matrici come valore che accompagna le chiavi. – wchlm

Problemi correlati