• Publicidad

Agregar un array como valor de un hash

¿Apenas comienzas con Perl? En este foro podrás encontrar y hacer preguntas básicas de Perl con respuestas aptas a tu nivel.

Agregar un array como valor de un hash

Notapor Alfumao » 2011-02-23 08:09 @381

Buenas tardes,

Escribo por si me podéis ayudar con el siguiente problema.

Necesito crear un hash a partir de varios arrays.

He escrito una subrutina para que el primer elemento de un array sea asignado como clave, y que el valor lo compongan el resto de los elementos del array. Pero tengo problemas para poblar (introducir las claves y los valores) el array.

Al intentar imprimir el hash (usando el modulo Data::Dumper) el array aparece vacío aunque con un número de claves que corresponde con el número de arrays que se han ido pasando a la subrutina...

Aquí os pongo la subrutina:

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. sub hoa {
  2.     use Data::Dumper;
  3.  
  4.     my(@TM)=@_;#paso el array a la sub
  5.  
  6.     my %HashT=();#inicializo el hash
  7.  
  8.     my $key = shift @TM;#saco el valor del array[0] para usarlo de clave del hash
  9.  
  10.     $HashT{"$key"}=1;#intento crear la clave
  11.  
  12.     foreach my $tm (@TM){
  13.         push(@{$HashT{$key}}, $tm);#voy metiendo cada valor del array como valor dentro
  14.                                    #del array asignado a la clave
  15.     }
  16.     print Dumper(\%HashT);
  17.     return %HashT;
  18.  
  19. }
Coloreado en 0.003 segundos, usando GeSHi 1.0.8.4


Gracias de antemano por vuestra atención.
Alfumao
Perlero nuevo
Perlero nuevo
 
Mensajes: 178
Registrado: 2009-12-10 11:20 @514

Publicidad

Re: Agregar un array como valor de un hash

Notapor explorer » 2011-02-23 08:31 @397

Comenta o quita la línea 10.

Es decir... cuando creas $HashT{"$key"} = 1; estás diciendo que lo que contiene el valor correspondiente a la clave es el número '1', pero dentro del bucle, de repente estás diciendo a Perl que no, que en realidad querías meter una referencia a un array.

Si al principio del programa hubieras puesto use strict; te habría avisado con esto:
Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
Can't use string ("1") as an ARRAY ref while "strict refs" in use at /media/500_1/home/explorer/Documentos/Desarrollo/code_24894.pl line 19.
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4

O sea, que Perl no puede usar la cadena "1" como una referencia a un array, que es lo que está viendo push().

En cambio, si quitas la línea 10, cuando entra en el bucle, el primer push() creará la clave e inicializará el valor con la referencia a un array. Y dentro del array, guardará el valor de $tm.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14480
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Agregar un array como valor de un hash

Notapor Alfumao » 2011-02-23 08:52 @411

Gracias, explorer.

Siempre uso strict, como tu me recomendaste hace ya tiempo.

He hecho un programilla de prueba (debería haberlo hecho antes de postear la duda) y me funciona.

El problema en el programa más grande era que yo hacía la llamada a la subrutina en un lugar incorrecto, por lo que el array que le pasaba estaba vacío.

Ahora me surge otra duda, derivada de esto.

Al ejecutar el programa con esta subrutina dentro de otro bucle, cada vez que paso un array a la subrutina, el %HashT se reinicia, de forma que cada vez está compuesto solo de la variable derivada del array introducido en la subrutina.

¿Cómo podría pasar el %HashT (que obtengo como retorno de la subrutina) cada nueva iteración del bucle, para no perder las variables introducidas?

¿Podría hacerlo así?
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. &hoa (@TM, %HashT);
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

quitando así de la subrutina, la línea:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. my %HashT=();#inicializo el hash
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

Muchas gracias.
Alfumao
Perlero nuevo
Perlero nuevo
 
Mensajes: 178
Registrado: 2009-12-10 11:20 @514

Re: Agregar un array como valor de un hash

Notapor explorer » 2011-02-23 10:16 @469

No, no puedes hacerlo así.

Hay que recordar que los argumentos a una subrutina son "desplegados", por lo que todos los elementos del array se mezclarán con las claves y valores del hash.

Una opción es pasar referencias (no probado):
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. my %HashT;
  2.  
  3. # bucle...
  4. {
  5.     my @TM = ...;
  6.     hoa(\@TM, \%HashT);                 # solo dos argumentos
  7.     # vemos el resultado
  8.     # ...
  9. }
  10.  
  11. sub hoa {
  12.     my ($tm_ref, $hash_ref) = @_;       # solo dos argumentos
  13.  
  14.     my $key = shift @$tm_ref;
  15.  
  16.     for my $tm (@$tm_ref) {
  17.         push @{$hash_ref->{$key}}, $tm; # voy metiendo cada valor del array como valor dentro
  18.                                         # del array asignado a la clave
  19.     }
  20. }
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14480
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Agregar un array como valor de un hash

Notapor Ulloa » 2011-03-07 17:50 @785

Hola, explorer, tengo una duda y quiero aprovechar que acá utilizas una expresión, tal como:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
for my $tm (@$tm_ref) {
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


No me queda clara la función de @$. ¿Puedes explicarme o decirme dónde encuentro una explicación? Me cuesta mucho todavía buscar información en perldoc.
Ulloa
Perlero nuevo
Perlero nuevo
 
Mensajes: 8
Registrado: 2011-03-04 15:36 @692

Re: Agregar un array como valor de un hash

Notapor explorer » 2011-03-07 18:28 @811

$tm_ref es una referencia a un array (por eso la hemos llamado _ref), que es lo que pasamos a la función: no pasamos el array sino una referencia a él.

Pero en el bucle queremos acceder al array (a los elementos del array).

Por eso, si

$tm_ref

es una referencia a un array, ponemos un '@' delante

@$tm_ref

que es lo mismo que

@{$tm_ref}

entonces, estamos "desreferenciando" la referencia al array, por lo que obtenemos el array (con sus elementos).

Luego, entonces, el bucle for() está recorriendo los elementos del array referenciado por $tm_ref.

Más información en perldoc perlref, en la sección Using References (de momento, en inglés).
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14480
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España


Volver a Básico

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 4 invitados