• Publicidad

Error inexplicable en array dentro de hash

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

Error inexplicable en array dentro de hash

Notapor Sombrerero_Loco » 2009-02-11 04:31 @229

Cuando ejecuto esto:

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
(open (FICHEROCFG, "<$fichero_cfg") or die "No se puede abrir el fichero de configuracion de transacciones $fichero_cfg!!\n";
while ($linea=<FICHEROCFG>) {
    ($var1,$var2,$var3,$var4) = split (",", $linea);
    $indice = $#{$db{$var1}} + 1;
    $db{$var1}{'counter'} = '';
    $db{$var1}[$indice]{'Entidad'} = $var2;
    $db{$var1}[$indice]{'Agrupacion'} = $var3;
    $db{$var1}[$indice]{'Transaccion'} = $var4;
}
while (($data_contador, $data_cod_entidad, $data_cod_agr, $data_cod_operacion) = $sth1_do->fetchrow_array)  {
    foreach $cn_nombre (keys (%db)) {
        foreach $cn_indice (0..$#{ $db{$cn_nombre}} ) {
            if ($db{$cn_nombre}[$cn_indice]{'Entidad'} == $data_cod_entidad and $db{$cn_nombre}[$cn_indice]{'Agrupacion'} == $data_cod_agr) {
                $db{$cn_nombre}{'contador'} = $rsv_contador++;
            }
            else {
                next;
            }
        }
    }
}
Coloreado en 0.004 segundos, usando GeSHi 1.0.8.4


El compilador me dice que en la línea
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
$db{$var1}{'counter'} = '';
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
"Not a HASH reference at line 39, <FICHEROCFG> line 1"

Lo que estoy leyendo es información de un fichero de este estilo:

Código: Seleccionar todo
NOMBRE1,01,02,04
NOMBRE1,02,03,04
NOMBRE2,03,05,04
NOMBRE2,05,06,04


Para que me vaya metiendo en un hash lo siguiente:
Nombre encontrado, un array con los siguientes datos: 01,02,04 (y los que, aunque siendo números diferentes, tengan el mismo nombre, como diferentes maneras de llamar a los mismo) y que cada vez que lo encuentre, me cuente uno para saber, cuántos tengo de cada uno.

Y las preguntas son:
1) ¿Por qué me los saca en el orden de Entidad, contador, transacción y Agrupación si los tengo colocados en otro orden? (mera pijada y/o curiosidad)
2) Si en vez de poner lo que os he puesto más arriba, sustituyo la siguiente línea:

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
$db{$cn_nombre}{'contador'} = $rsv_contador++;
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

por
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
$db{$cn_nombre}[$cn_indice]{'contador'} = $rsv_contador++;
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

me funciona pero me cuenta demasiados registros:

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
$VAR3 = 'NOMBRE1';
$VAR4 = [
          {
            'Entidad' => 283,
            'contador' => 8986,
            'Transaccion' => '04
'
,
            'Agrupacion' => 24
          }
        ];
$VAR5 = 'NOMBRE2;
$VAR6 = [
          {
            '
Entidad' => '01',
            '
contador' => 9018,
            '
Transaccion' => '04
',
            '
Agrupacion' => '01'
          },
          {
            '
Entidad' => '01',
            '
contador' => 6487,
            '
Transaccion' => '04
',
            '
Agrupacion' => 23
          },
          {
            '
Entidad' => '01',
            '
contador' => 8987,
            '
Transaccion' => '04
',
            '
Agrupacion' => 25
          }
        ];
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


Curioso, ¿verdad?

¡Gracias!
Sombrerero_Loco
Perlero nuevo
Perlero nuevo
 
Mensajes: 42
Registrado: 2008-11-11 11:20 @514

Publicidad

Notapor explorer » 2009-02-11 06:01 @292

El problema es el siguiente: en la línea 38 estás diciendo
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
$indice = $#{$db{$var1}} + 1;
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
que quiere decir que quieres calcular el $indice disponible siguiente del array que está contenido dentro del hash %db, correspondiente a la clave $var1.

Es decir, tenemos un hash que en cada valor almacena un array.

Pero... en la línea siguiente estás diciendo otra cosa distinta:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
$db{$var1}{'counter'} = '';
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
Aquí, estamos indicando que lo que realmente hay dentro del hash es otro hash. Y en este caso, ese hash tiene un elemento con clave 'counter'.

Y para redondear el problema, en la línea siguiente, volvemos al origen:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
$db{$var1}[$indice]{'Entidad'} = $var2;
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
que volvemos a tener el array dentro del hash %db. Como añadido, indicamos que cada elemento del array almacena una referencia a un hash.

Vamos... un jaleo de cambio de estructuras, línea a línea...

Esta es una posibilidad:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
#!/usr/bin/perl
use strict;
use warnings;
use diagnostics;

use Data::Dumper;

my $fichero_cfg = 'kk.txt';

open FICHEROCFG, "<$fichero_cfg"
    or die "No se puede abrir el fichero de configuracion de transacciones $fichero_cfg!!\n";

my %db;

while (my $linea = <FICHEROCFG>) {
    chomp $linea;
    my ($var1,$var2,$var3,$var4) = split ',', $linea;

    my $indice = $#{$db{$var1}} + 1;

    $db{$var1}[$indice]{contador}    = 0;
    $db{$var1}[$indice]{Entidad}     = $var2;
    $db{$var1}[$indice]{Agrupacion}  = $var3;
    $db{$var1}[$indice]{Transaccion} = $var4;
}

close FICHEROCFG;

print Dumper \%db;

__END__
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
que sale:
Código: Seleccionar todo
$VAR1 = {
          'NOMBRE1' => [
                         {
                           'Entidad' => '01',
                           'contador' => 0,
                           'Transaccion' => '04',
                           'Agrupacion' => '02'
                         },
                         {
                           'Entidad' => '02',
                           'contador' => 0,
                           'Transaccion' => '04',
                           'Agrupacion' => '03'
                         }
                       ],
          'NOMBRE2' => [
                         {
                           'Entidad' => '03',
                           'contador' => 0,
                           'Transaccion' => '04',
                           'Agrupacion' => '05'
                         },
                         {
                           'Entidad' => '05',
                           'contador' => 0,
                           'Transaccion' => '04',
                           'Agrupacion' => '06'
                         }
                       ]
        };
y ahora sí que tenemos el hash, conteniendo cada clave un array, y cada elemento del array es otro hash.

Las preguntas.
1) No se conoce el orden en que se guardan las claves dentro de un hash. Se considera pseudo aleatorio, pero en realidad es el resultado de una operación de hash (de ahí el nombre). Esto nos obliga a hacer más trabajo de programación si queremos que la información salga en un determinado orden. Pero esta desventaja es pequeña comparada con todas las ventajas que ofrecen los hash.

Pero como el Perl, casi todo tiene solución.

Sí que hay una forma de tener un hash que guarde las claves en el mismo orden en que las guardas.

Con el módulo Tie::IxHash (y otros) puedes conseguirlo, pero a cambio de una pérdida de velocidad, como advierte perlfaq4 # How can I always keep my hash sorted?.
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

Notapor Sombrerero_Loco » 2009-02-11 07:31 @355

Entiendo... pero me surge una duda... ¿no es posible definir que un hash tenga esta estructura?

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
HASH
       CLAVE1
                  ARRAY1
                              CLAVE1.1 = DATO1
                              CLAVE1.2 = DATO2

       CLAVE2
                   = DATO3
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


¿Esto no sería viable? Ya que una vez que le digo que ponga un array entre medias, me obliga a seguir siempre teniendo un array.

Yo quiero que la CLAVE1 tenga un array con hash dentro (CLAVE1.1 & CLAVE1.2 == DATO1 & DATO2) y que en el mismo hash la CLAVE2 tenga un valor igual a DATO3... ¿eso no es posible?

Espero haberme explicado bien...

¡Gracias!
Sombrerero_Loco
Perlero nuevo
Perlero nuevo
 
Mensajes: 42
Registrado: 2008-11-11 11:20 @514

Notapor explorer » 2009-02-11 08:07 @380

Sí, si que es posible. Puedes hacerlo porque no tiene nada que ver el ARRAY1 con el DATO3.

Solo tienes que controlar qué es lo que guardas en cada sitio.
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

Notapor Sombrerero_Loco » 2009-02-11 09:48 @450

¿Y cómo?
¿Separándolo y no metiéndolo en el bucle while? ¿Haciéndolo antes de ese bucle?
Sombrerero_Loco
Perlero nuevo
Perlero nuevo
 
Mensajes: 42
Registrado: 2008-11-11 11:20 @514

Notapor explorer » 2009-02-11 10:48 @492

En el momento de meter el dato, por ejemplo. Como no sabemos qué es lo que va a contener, tenemos que ver, en cada vuelta, qué es lo que contiene antes.

Si no hay nada, guardas el dato como escalar.

Si hay algo, entonces tienes que ver qué es que hay dentro (con la función ref(), por ejemplo).

Si lo que contiene es un escalar, guarda en él un array con dos elementos: el anterior y el nuevo.

Si hay un array, guardamos el nuevo dato en él con push().

Queda más simple si siempre usamos un array, desde luego, porque solo tenemos que usar el push().
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 1 invitado

cron