• Publicidad

Problemas con subrutina

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

Problemas con subrutina

Notapor preiddy » 2007-08-14 09:22 @432

Aunque he dejado apartado por el momento el tema de la similaridad en una cadena de texto, me he puesto a identificar las cadenas de direcciones y asignarles un país y su respectivo continente de manera automática. Para ello me hice una subrutina que carga en un hash el país y su respectivo continente, lo leo de una tabla en mi BD.
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
sub Paises
{
    my $db= conexion a la BD;
    my $reg= $db->prepare("SELECT * FROM paises");
    $reg->execute();
    while (my @lineas=$reg->fetchrow_array())
    {           $pais{$lineas[0]} = [$lineas[1],$lineas[2],$lineas[3],$lineas[4],$lineas[5]];          
    }
    return(%pais);
    $reg->finish();
    $db->disconnect();
}
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4

esto funciona, sé que es mejorable, pero funciona.

Luego que tengo el hash quiero que por cada dirección almacenada en otra tabla se asigne, el país y el resto de valores guardados, para ello hago una consulta a la BD a la tabla de direcciones y busco.
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
while (my @lineas=$sth->fetchrow_array())
{
foreach my $cod(keys %res)
{
        if ($lineas[0]=~/$cod.$/i)
        {
        #print "$lineas[0]=$cod;$res{$cod}[0];$res{$cod}[1];$res{$cod}[2];$res{$cod}[3];$res{$cod}[4]\n";
        print "$res{$cod}[3]-$cod\n";
        }
        #else
        #{print "$lineas[0]=SIN IDENTIFICAR\n";}
}
}
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

funciona muy bien para cada dirección localizada, si no está no la muestra. Pero si descomento el else para mostrar la que no ha identificado, por cada dirección le asigna su país correspondiente que ubico en el hash y luego se repite por cada valor del hash la palabra SIN IDENTIFICAR.

Obteniendo el siguiente resultado:
Código: Seleccionar todo
ucv, caracas, venezuela = venezuela, america del sur. america
ucv, caracas, venezuela = SIN IDENTIFICAR
ucv, caracas, venezuela = SIN IDENTIFICAR
ucv, caracas, venezuela = SIN IDENTIFICAR .....

y así hasta 239 veces que es el número de elementos que tiene el hash y por cada dirección que son unas 100mil.
¡¡¡Una ayudita por favor!!!!, no sé qué estoy haciendo mal.
preiddy
Perlero nuevo
Perlero nuevo
 
Mensajes: 70
Registrado: 2006-03-29 05:43 @280
Ubicación: Madrid, España

Publicidad

Notapor monoswim » 2007-08-14 11:55 @538

Es que tienes un bucle adentro de otro, en verdad está haciendo lo que sale en else, solo que no te lo muestra, eso te consumirá muchísimo procesador...

No es recomendable hacer un bucle dentro de otro... (while y foreach)

Saludos
MonoSwim
Perl Programming Language
Avatar de Usuario
monoswim
Perlero nuevo
Perlero nuevo
 
Mensajes: 452
Registrado: 2003-11-18 16:13 @717
Ubicación: Buenos Aires

Notapor explorer » 2007-08-14 12:05 @545

Yo no veo fallos... es decir, Perl está haciendo lo correcto: por cada dirección de la tabla, la comparas con todas las claves de país anteriores. Si coincide haces una cosa, pero sino, otra. El resultado es justo el que comentas: 239 por 100 mil.

Eso... o no acabo de verlo...

Me gustaría ver un ejemplo de como son las dos tablas de la base de datos.
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 preiddy » 2007-08-14 12:55 @580

No, fallo no tiene, el problema es que no necesito que me diga 238 veces SIN IDENTIFICACION.

Monoswim, me dices que no es bueno anidar bucles, entonces, ¿cómo hago para que una variable que extrae la información de una tabla busque en otra variable que también extrae la información de otra tabla? ¿Cual es la solución? ¿usar archivos de texto y tablas en una BD?

Estoy desorientado, no sé entonces cómo debo abordarlo.

Explorer, los datos en la tabla dirección son iguales a los que mostré en el mensaje de similaridad, aquí un poco más de datos, :lol:
Código: Seleccionar todo
1ST THERAPEUT INST SOCIAL SECUR, ATHENS, GREECE.
2 MAYO NATL HOSP, LIMA, PERU.
A ST GYORGH MED UNIV, DEPT PEDIAT, SZEGED, HUNGARY.
AAPG, TULSA, OK 74119 USA.
AARHUS AMTSSYGEHUS HOSP, MED AFDELING C, AARHUS, DENMARK.
AARHUS UNIV HOSP, DK-8000 AARHUS, DENMARK.
AB BIODISK, SOLNA, SWEDEN.
ABBOTT LABS INC, ROSS DIV, COLUMBUS, OH USA.
ABBOTT LABS INC, ROSS PROD DIV, COLUMBUS, OH 43215 USA.
ABBOTT LABS, N CHICAGO, IL 60064 USA.
ABDAL MALEK ESSAADI UNIV, FAC SCI, APPL PHYS CHEM LAB, TETOUAN, MOROCCO
AES VENEZUELA, CARACAS 1010, VENEZUELA.
AF IOFFE PHYS TECH INST, ST PETERSBURG 194021, RUSSIA.


Los datos en la tabla país los tome de la norma ISO 3166 y son: nombre del país, código numérico, tres letras y dos letras del nombre. Cuatro campos en total.
Código: Seleccionar todo
Afghanistan 4 AFG AF
Åland Islands 248 ALA AX
Albania 8 ALB AL
Algeria 12 DZA DZ
American Samoa 16 ASM AS
Andorra 20 AND AD


El resultado que esperaba que saliera de manera correcta, seria:

Código: Seleccionar todo
UNIV LOS ANDES, FAC MED, NEUROENDOCRINOL LAB, DPTO FISIOPATOL, MERIDA, VENEZUELA. Venezuela 862 VEN VE
UNIV PARIS SUD, CNRS, PHOTOPHYS MOL LAB, F-91405 ORSAY, FRANCE. France 250 FRA FR
UNIV NEBRASKA,SCH BIOL SCI,LINCOLN,NE 68588. SIN IDENTIFICAR
UNIV N CAROLINA, DEPT GEOL SCI, CHAPEL HILL, NC 27599 USA.3 UNIV LOS ANDES, FAC MED, NEUROENDOCRINOL LAB, DPTO FISIOPATOL, MERIDA, VENEZUELA. Venezuela 862 VEN VE
preiddy
Perlero nuevo
Perlero nuevo
 
Mensajes: 70
Registrado: 2006-03-29 05:43 @280
Ubicación: Madrid, España

Notapor explorer » 2007-08-14 13:53 @620

Se me ocurre entonces lo siguiente: dentro del bucle foreach estás buscando qué país corresponde a la dirección que estás leyendo de la tabla. Entonces, una vez que le encuentres, con la ayuda del if, lo asignas o lo guardas, Y, a continuación, ejecutas un last; para que el bucle foreach termine inmediatamente.

Esta es una forma, pero lo ideal es que las claves extraídas de las direcciones nos diesen las claves de los países dentro del hash de países, por lo que no habría que hacer búsqueda ninguna.

Yo haría lo siguiente. Primero, normalizar los datos. Guardaría, en el hash de países, como claves, el nombre del país puesto, por ejemplo, en mayúscula.

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
$pais{ uc( $lineas[0] ) } = [ @lineas[1..5] ];
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


Luego, al recorrer las direcciones, transformo el foreach en un intento de correspondencia hash. En el intento anterior veo que estás intentando hacer corresponder la línea devuelta con el código de país, pero mirando solo si coincide en su parte final -junto con un punto-. Bueno, entonces haremos el proceso inverso: de la línea devuelta por la tabla, intentaremos coger el país y luego intentar hacerle buscar en la tabla de países.

(No probado)
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
while (my $linea = $sth->fetch) {

    # Buscar el país al final de la dirección
    if ( my ($pais) = $linea->[0] =~ /(\w+)\.$/ ) {

        # Tenemos un país, lo buscamos por la tabla de países
        my $datos_del_pais = join " ", @{ $paises{ uc($pais) } };
        if ( $datos_del_pais ) {
            print "Localizado: $linea->[0] $datos_del_pais";
        }
        else {
            print "$pais no localizado en la tabla de países.\n";
        }
    }
    else {
        print "No pude extraer el país de $linea->[0]\n";
    }
}
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

He cambiado algunas cosas (fetchall por fetch, ya que sólo recuperas un campo, creo; y la hash %res por %paises).

Actualización: Faltaba un 'join' para mostrar todos los datos del país, pues estaba guardado como un array anónimo.
Última edición por explorer el 2007-08-15 16:58 @749, editado 1 vez en total
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 preiddy » 2007-08-15 10:50 @493

lo he ejecutado y este es lo que se ha obtenido
Código: Seleccionar todo
No pude extraer el pa?s de ARRAY(0x18701d8)
No pude extraer el pa?s de ARRAY(0x18701d8)
No pude extraer el pa?s de ARRAY(0x18701d8)
No pude extraer el pa?s de ARRAY(0x18701d8)
No pude extraer el pa?s de ARRAY(0x18701d8)
No pude extraer el pa?s de ARRAY(0x18701d8)
No pude extraer el pa?s de ARRAY(0x18701d8)
No pude extraer el pa?s de ARRAY(0x18701d8)
No pude extraer el pa?s de ARRAY(0x18701d8)


Voy a revisar línea a línea, para ubicar dónde está el fallo, aunque creo que es la primera línea.
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
if ( my ($pais) = $linea =~ /(\w+)\.$/ )
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

Cuando lo termine de revisar envío los resultados.
Muchas gracias por la ayuda.
preiddy
Perlero nuevo
Perlero nuevo
 
Mensajes: 70
Registrado: 2006-03-29 05:43 @280
Ubicación: Madrid, España

Notapor explorer » 2007-08-15 16:59 @749

El fallo es que estaba usando fetch(), que es un alias de un fetchrow_arrayref, por lo que eso me devuelve una referencia a un array... y no el contenido de línea como yo quería.

Ya he editado el código y he cambiado $linea por $linea->[0]. Prueba a ver ahora.
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 preiddy » 2007-08-17 12:02 @543

ok, lo probaré y ya te contaré como fue. Muchas gracias de nuevo.
Ahora tengo una duda, ¿es posible buscar en un hash en cualquier parte?
Me explico mejor: si tengo un hash con una clave y tres valores asociados, tengo una palabra en otra variable y quiero ver si ese hash lo tiene, ya sea la clave o cualquier otro valor. ¿Es posible?
preiddy
Perlero nuevo
Perlero nuevo
 
Mensajes: 70
Registrado: 2006-03-29 05:43 @280
Ubicación: Madrid, España


Volver a Básico

¿Quién está conectado?

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