• Publicidad

Ayuda con hash de hashes

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

Ayuda con hash de hashes

Notapor asegurac » 2009-10-26 19:43 @863

Hola.

Les escribo para lo siguiente:

Tengo varios hash de hashes; con los valores de los mismos necesito hacer algunas comparaciones y contabilizarlas. Al final con los resultados de las comparaciones deseo obtener una matriz. A continuación coloco un segmento de la salida de la impresión de los hash de hashes y el código que estoy utilizando:

Esta es la salida de los hash de hashes
Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
2hbsA   97      0.196   1       -3.769
2hbsA   98      0.126   1       -5.233
2hbsA   99      0.131           -6.971
2hbsB   10      0.191           -5.591
2hipA   10      0.281           -12.156
2hipA   11      0.274           -13.044
2j9uB   123     0.102   1       -4.653
2j9uB   124     0.199           -3.102
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4


Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
# Código

my $intervi=0;
my $intervii=0;
my $countfdb=0;

foreach $x (sort keys %hash){
       
        for $y (sort keys %{$hash{$x}}){
        #print RES "$x\t$y\t$hash{$x}{$y}\t$hfiredb{$x}{$y}\t$hanolea{$x}{$y}\n"; esto imprime los valores que coloque anteriormente
#aquí empiezan las comparaciones
        $valoran=$hanolea{$x}{$y};
        $valorfl=$hash{$x}{$y};
        $valorfdb=$hfiredb{$x}{$y};
       
        if (($valorfl >0)&&($valorfl<0.7)&&($valoran >0)&&($valoran<2.5)) {
        $intervi++;
       
                if ($valorfdb == 1){
       
                        $countfdb++;
                }
        }
        if (($valorfl >0)&&($valorfl<0.7)&&($valoran >2.5)&&($valoran<5)) {
        $intervi++;
       
                if ($valorfdb == 1){
       
                        $countfdb++;
                }
        }
}
print "$intervi\t$intervii\t$countfdb\n";
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4


Este código me funciona; el problema que tengo es que son 8 intervalos, de manera que la matriz resultante sería el producto de hacer esas comparaciones 8x8. No tengo idea de cómo hacer las múltiples comparaciones y así evitar llenar de if() mi código. Espero haber sido claro, si no pido disculpas por adelantado.

Saludos.
Última edición por explorer el 2009-10-27 03:23 @182, editado 1 vez en total
Razón: Ortografía, bloques de código
asegurac
Perlero nuevo
Perlero nuevo
 
Mensajes: 34
Registrado: 2008-10-31 05:52 @286

Publicidad

Re: Ayuda con hash de hashes

Notapor explorer » 2009-10-27 03:32 @189

¿Los intervalos son de igual tamaño?

Es decir, el intervalo para $valorfl es siempre de un tamaño de 0,7 y el de $valoran de 2,5?

Entonces, solo tienes que aplicar un poco de matemáticas.
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: Ayuda con hash de hashes

Notapor asegurac » 2009-10-27 10:11 @466

Hola.

El tamaño de los intervalos puede variar, de hecho me gustaría que fuera algún argumento que se le pasara a mi script para hacer varias pruebas y ver qué intervalos me serían más útiles.

Mi pregunta es cómo podría simplificar la operación de comparación sin tener que hacer repetidos "if" comparando todos contra todos los intervalos.

Ya he intentado varias cosas y no encuentro cómo hacerlo.

Gracias
asegurac
Perlero nuevo
Perlero nuevo
 
Mensajes: 34
Registrado: 2008-10-31 05:52 @286

Re: Ayuda con hash de hashes

Notapor explorer » 2009-10-27 12:06 @546

Esto es lo que he hecho:

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2. use strict;
  3. use warnings;
  4. use diagnostics;
  5.  
  6. my %hash = (
  7.     '2hbsA' =>
  8.             {
  9.                 97 => 0.196,
  10.                 98 => 0.126,
  11.                 99 => 0.131,
  12.             },
  13.     '2hbsB' =>
  14.             {
  15.                 10 => 0.191,
  16.             },
  17.     '2hipA' =>
  18.             {
  19.                 10 => 0.281,
  20.                 11 => 0.274,
  21.             },
  22.     '2j9uB' =>
  23.             {
  24.                123 => 0.102,
  25.                124 => 0.199,
  26.             },
  27. );
  28.  
  29. my %hfiredb = (
  30.     '2hbsA' =>
  31.             {
  32.                 97 => 1,
  33.                 98 => 1,
  34.             },
  35.     '2j9uB' =>
  36.             {
  37.                123 => 1,
  38.             },
  39. );
  40.  
  41. my %hanolea = (
  42.     '2hbsA' =>
  43.             {
  44.                 97 => -3.769,
  45.                 98 => -5.233,
  46.                 99 => -6.971,
  47.             },
  48.     '2hbsB' =>
  49.             {
  50.                 10 => -5.591,
  51.             },
  52.     '2hipA' =>
  53.             {
  54.                 10 => -12.156,
  55.                 11 => -13.044,
  56.             },
  57.     '2j9uB' =>
  58.             {
  59.                123 => -4.653,
  60.                124 => -3.102,
  61.             },
  62. );
  63.  
  64. my $intervi   = 0;
  65. my $count_fdb = 0;
  66.  
  67. my $rango_fl = $ARGV[0];
  68. my $rango_an = $ARGV[1];
  69.  
  70. for my $x (sort keys %hash) {
  71.  
  72.     for my $y (sort keys %{$hash{$x}}) {
  73.  
  74.         # esto imprime los valores que coloque anteriormente
  75.         #print "$x\t$y\t$hash{$x}{$y}\t$hfiredb{$x}{$y}\t$hanolea{$x}{$y}\n";
  76.  
  77.         my $valor_fl  = $hash   {$x}{$y};
  78.         my $valor_an  = $hanolea{$x}{$y};
  79.         my $valor_fdb = $hfiredb{$x}{$y} || 0;
  80.  
  81.         for my $i (  0 .. 7 ) {
  82.         for my $j ( -3 .. 3 ) {
  83.  
  84.             my $min_fl = $i      * $rango_fl;
  85.             my $max_fl = $min_fl + $rango_fl;
  86.             my $min_an = $j      * $rango_an;
  87.             my $max_an = $min_an + $rango_an;
  88.  
  89.             #print "Analizando [$min_fl,$max_fl) => $valor_fl : [$min_an,$max_an) => $valor_an\n";
  90.  
  91.             if (
  92.                 $valor_fl >= $min_fl  and
  93.                 $valor_fl <  $max_fl  and
  94.                 $valor_an >= $min_an  and
  95.                 $valor_an <  $max_an
  96.             ) {
  97.                 $intervi++;
  98.  
  99.                 $count_fdb++ if $valor_fdb == 1;
  100.             }
  101.         }}
  102.     }
  103.  
  104.     print "$intervi\t$count_fdb\n";
  105. }
  106.  
  107. __END__
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4


Lo que difiere con tu programa es lo siguiente.

He eliminado la variable $intervii porque no veo en el ejemplo ningún sitio donde se use.

En las líneas 66 y 67 se leen los rangos pasados por el usuario.

En la línea 79 inicializamos los valores desde los hash, salvo que %hfiredb no podría tener valor, por lo que, en ese caso, le ponemos un valor 0 (distinto del valor 1 que es el que nos interesa buscar).

De la 81 a la 101 está el doble bucle de 8x8 rangos, donde vamos variando los intervalos de búsqueda, que construimos en las líneas 84 a 87.

En la 91, hacemos la pregunta de si los valores que tenemos está dentro del intervalo, e incrementamos los contadores.

Con los datos introducidos, con
Sintáxis: [ Descargar ] [ Ocultar ]
Using bash Syntax Highlighting
./programa.pl 0.7 2.5
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4
me da
Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
3       2
4       2
4       2
6       3
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4


Nota: hay que tener en cuenta a la hora de hacer la comparación de los intervalos, qué parte, si la derecha o la izquierda, forma parte de la comparación. En el código, he puesto la parte izquierda (el valor menor del intervalo pertenece al intervalo). De ahí la diferencia de usar '[' y ')' como se indica en el print() comentado.

(Un poco de matemáticas).
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: Ayuda con hash de hashes

Notapor asegurac » 2009-10-27 13:05 @587

Hola,

Muchas gracias por tu respuesta, la verdad que soy muy pero muy malo para las matemáticas (hasta las más simples), solo tengo una duda.

Por ejemplo, estos son los valores que se utilizan para las comparaciones:

Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
0.196   1       -3.769
0.126   1       -5.233
0.131           -6.971
0.191           -5.591
0.281           -12.156
0.274           -13.044
0.102   1       -4.653
0.199           -3.102
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4


Como puedes ver con este segmento de todas las posibles combinaciones de intervalos darían cero porque ninguno de los valores en %hanolea es positivo.

Posiblemente no me expliqué bien, pero lo que yo esperaría es una matriz de este tipo:

Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
0    2.5 5 7.5 10 12.5 15 17.5 20
################################
0.7# 0/0
1.4#
2.1#
2.8#
3.5#
4.2#
4.9#
5.6#
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4


En el ejemplo "0/0", el primer 0 es el valor de $intervi y el otro después de la "/" correspondería a $count_fdb.
asegurac
Perlero nuevo
Perlero nuevo
 
Mensajes: 34
Registrado: 2008-10-31 05:52 @286

Re: Ayuda con hash de hashes

Notapor explorer » 2009-10-27 16:01 @709

Revisando con más calma la pregunta anterior, se ve entonces que hay un fallo en el programa: no hay que hacer las estadísticas de intervalos que coinciden con los valores, sino que hay que recorrer los intervalos y comprobar cuántos valores hay en cada uno de ellos.

Hay que mover los bucles.

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2. use strict;
  3. use warnings;
  4. use diagnostics;
  5.  
  6. my %hash = (
  7.     '2hbsA' =>
  8.             {
  9.                 97 => 4.96,
  10.                 98 => 0.126,
  11.                 99 => 0.131,
  12.             },
  13.     '2hbsB' =>
  14.             {
  15.                 10 => 0.191,
  16.             },
  17.     '2hipA' =>
  18.             {
  19.                 10 => 2.81,
  20.                 11 => 0.274,
  21.             },
  22.     '2j9uB' =>
  23.             {
  24.                123 => 0.102,
  25.                124 => 0.199,
  26.             },
  27. );
  28.  
  29. my %hfiredb = (
  30.     '2hbsA' =>
  31.             {
  32.                 97 => 1,
  33.                 98 => 1,
  34.             },
  35.     '2j9uB' =>
  36.             {
  37.                123 => 1,
  38.             },
  39. );
  40.  
  41. my %hanolea = (
  42.     '2hbsA' =>
  43.             {
  44.                 97 => 3.769,
  45.                 98 => -5.233,
  46.                 99 => -6.971,
  47.             },
  48.     '2hbsB' =>
  49.             {
  50.                 10 => -5.591,
  51.             },
  52.     '2hipA' =>
  53.             {
  54.                 10 => 12.56,
  55.                 11 => -13.044,
  56.             },
  57.     '2j9uB' =>
  58.             {
  59.                123 => -4.653,
  60.                124 => -3.102,
  61.             },
  62. );
  63.  
  64. ## Lectura de los parámetros
  65. my $rango_fl = $ARGV[0];
  66. my $rango_an = $ARGV[1];
  67.  
  68.  
  69. ## Cálculo de los intervalos
  70. my @intervalos_fl = map { $rango_fl * $_ } 0 .. 7;
  71. my @intervalos_an = map { $rango_an * $_ } 0 .. 7;
  72.  
  73.  
  74. # Cabecera de la matriz
  75. print "\t", join("\t", @intervalos_an), "\n";
  76. print '#' x (8 * (@intervalos_an + 1)), "\n";
  77.  
  78.  
  79. # Bucle por toda la matriz
  80. for my $i (  0 .. 7 ) {
  81.  
  82.     printf '%7s', $intervalos_fl[$i] . ' #';        # Cabecera izquierda
  83.  
  84.     for my $j (  0 .. 7 ) {
  85.  
  86.         my $min_fl = $intervalos_fl[$i];
  87.         my $max_fl = $min_fl + $rango_fl;
  88.         my $min_an = $intervalos_an[$j];
  89.         my $max_an = $min_an + $rango_an;
  90.  
  91.         # Inicio del análisis
  92.         my $intervi   = 0;
  93.         my $count_fdb = 0;
  94.  
  95.         # Estadística
  96.         for my $x (sort keys %hash) {
  97.  
  98.             for my $y (sort keys %{$hash{$x}}) {
  99.  
  100.                 my $valor_fl  = $hash   {$x}{$y};
  101.                 my $valor_an  = $hanolea{$x}{$y};
  102.                 my $valor_fdb = $hfiredb{$x}{$y} || 0;
  103.  
  104.                 if (
  105.                     $valor_fl >= $min_fl  and
  106.                     $valor_fl <  $max_fl  and
  107.                     $valor_an >= $min_an  and
  108.                     $valor_an <  $max_an
  109.                 ) {
  110.                     $intervi++;
  111.  
  112.                     $count_fdb++ if $valor_fdb == 1;
  113.                 }
  114.  
  115.             }
  116.         }
  117.  
  118.         print "\t$intervi/$count_fdb";
  119.     }
  120.  
  121.     print "\n";
  122. }
  123.  
  124. __END__
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4

Ejecutando, sale
Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
explorer@casa:~/Documents/Desarrollo> ./code_19463.pl 0.7 2.5
        0       2.5     5       7.5     10      12.5    15      17.5
########################################################################
    0 # 0/0     0/0     0/0     0/0     0/0     0/0     0/0     0/0
  0.7 # 0/0     0/0     0/0     0/0     0/0     0/0     0/0     0/0
  1.4 # 0/0     0/0     0/0     0/0     0/0     0/0     0/0     0/0
  2.1 # 0/0     0/0     0/0     0/0     0/0     0/0     0/0     0/0
  2.8 # 0/0     0/0     0/0     0/0     0/0     1/0     0/0     0/0
  3.5 # 0/0     0/0     0/0     0/0     0/0     0/0     0/0     0/0
  4.2 # 0/0     0/0     0/0     0/0     0/0     0/0     0/0     0/0
  4.9 # 0/0     1/1     0/0     0/0     0/0     0/0     0/0     0/0
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4


(He modificado un par de valores para que saliese algún '1')

Actualización: Modificado el cálculo de los intervalos para que siempre empiece en 0.
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: Ayuda con hash de hashes

Notapor asegurac » 2009-10-27 16:12 @717

Hola. He seguido tus instrucciones y he cambiado ambos rangos de 0 a 7; sin embargo todavía hay algunas cosas que no entiendo. Por ejemplo, si modificas un valor por ejemplo "-3.769" por "3.769" cuando se realicen las comparaciones, solo una de ellas será verdadera, que es la combinación de intervalos 0.7 y 5. Sin embargo al momento de imprimir, obtengo como resultado:

Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
1       1
1       1
1       1
1       1
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4


¿No deberían aparecer 64 pares de valores, un par de unos y los restantes serían ceros?

Así entonces en la matriz que pongo en uno de los mensajes anteriores en la combinación 0.7 y 5 debería aparecer 1\1 y las demás combinaciones de la matriz deberían aparecer 0\0. ¿Qué crees que esté fallando? ¿Algún print()?

Nuevamente, muchas gracias por tu ayuda.
asegurac
Perlero nuevo
Perlero nuevo
 
Mensajes: 34
Registrado: 2008-10-31 05:52 @286

Re: Ayuda con hash de hashes

Notapor explorer » 2009-10-27 16:20 @722

Según la condición que has puesto, no solo tienes que cambiar uno de los valores de %hash, sino también de %hanolea.

De todas maneras, mira el segundo programa que te he mandado.
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: Ayuda con hash de hashes

Notapor asegurac » 2009-10-27 18:55 @830

¡¡¡Excelente!!!

¡¡¡Muchas gracias!!!
asegurac
Perlero nuevo
Perlero nuevo
 
Mensajes: 34
Registrado: 2008-10-31 05:52 @286


Volver a Básico

¿Quién está conectado?

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