2011-10-26 24 views
5

Tengo un problema donde los pares de números se asignan a otros pares de números. Por ejemplo, (1,2) -> (12,97). Algunos pares pueden mapear a otros pares múltiples, entonces lo que realmente necesito es la capacidad de mapear un par en una lista de listas, como (1,2) -> ((12,97), (4,1)). Al final del día, quiero procesar cada uno de los valores (es decir, cada lista de listas) por separado.Hash de Perl cuando las claves y los valores son referencias de matriz

En Python, que podía hacer esto simplemente diciendo:

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

Sin embargo, en Perl, tengo que usar árbitros para las claves y valores. Así que puedo decir:

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

Pero, ¿qué ocurre cuando aparece otro par (x2, y2)? Incluso si x2 == x1 y y2 == y1, $ keyref = [x2, y2] diferirán del keyref anterior generado, por lo que no veo una forma de hacer la búsqueda. Por supuesto, podría comparar (x2, y2) con cada clave hash desreferenciada, pero después de todo, Dios nos dio tablas hash precisamente para evitar la necesidad de hacerlo.

¿Existe una solución de Perl?

Gracias,

-W.

+0

No puede usar una referencia como clave. (al menos no sin usar un * hash * atado) –

Respuesta

0

Terminé usando la solución de zócalo de marionetas (en la forma de la Opción 3 de Michael Carmen). FYI, aquí hay un pequeño script de Perl que realiza todas las operaciones que necesito en mi aplicación.

Líneas impresas 2:, 3: y 4:, 5: simplemente use una sintaxis diferente para hacer lo mismo, y las líneas 0: y 1: solo pretendían ser controles de cordura en el camino.

Lo que esto agrega a la solución sugerida es el uso de una matriz de matrices como el valor que acompaña a una clave.

@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. Hubiera agregado esto como un comentario pero fue demasiado largo, y pensé que tenía sentido incluir un ejemplo trabajado.

+0

Felicitaciones por la solución. Cuando pueda, asegúrese de marcar su respuesta como 'aceptada' para que otros puedan aprender de su éxito. Saludos ~ –

10

En Perl, todas las teclas hash son cadenas, o están "codificadas" antes de la búsqueda. Usar una referencia de matriz como clave generalmente es el enfoque equivocado.

¿Qué hay de usar un hash "bidimensional"?

$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

Brilliant! Gracias. – wchlm

2

Como casi todo en Perl, TMTOWTDI.

Opción 1: Uso de emulación matriz multidimensional

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

Véase también la documentación de la variable incorporada $;.

Opción 2: Utilice el módulo Hash::MultiKey

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

Opción 3: Utilice un HoH (hash del hash) en lugar

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

Terminé usando la solución de Socket Puppet (en forma de su Opción 3). FYI, aquí hay un pequeño script de Perl que realiza todas las operaciones que necesito hacer en mi aplicación. Líneas impresas 2:, 3: y 4:, 5: simplemente use una sintaxis diferente para hacer las mismas cosas, y 0: y 1: solo pretendían ser controles de cordura en el camino. Lo único que se agrega a estos ejemplos es el uso de una matriz de matrices como el valor que acompaña a las claves. – wchlm

Cuestiones relacionadas