• Publicidad

Comparación de dos listas

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

Comparación de dos listas

Notapor nrikex » 2007-06-22 13:38 @609

Hola:

Ojalá me pudieran ayudar a entender la lógica de los siguientes bucles porque aparentemente no es como yo creo. Me explico: lo que quiero es lo siguiente, abrir dos archivos para compararlos y crear un tercero con los elementos que NO estén en el segundo archivo:

el código que utilizo es el siguiente:

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
#!/usr/bin/perl -w
       
        use strict;
       
        my $i;
        my @archivo1;
        my @archivo2;
        my $arch3 = 'archivo-sin-bc.txt';
       
        @archivo1 = 'aaa bbb ccc ddd eee';
        @archivo2 = 'bbb ccc';
       
        open (ARCH3,">$arch3");
       
       
        while (<@archivo1>)
        {
                foreach $i (@archivo2)
                {
                        if ( $_ =~ /$i/)
                        {
                               
                                next;
                       
                        } else {
                               
                        print ARCH3 "$i\n";
                       
                        }
                       
               
                       
                }
               
        }
Coloreado en 0.003 segundos, usando GeSHi 1.0.8.4


pero al ejecutar el script y checar el tercer archivo obtengo lo siguiente:

Código: Seleccionar todo
bbb ccc
bbb ccc
bbb ccc
bbb ccc


No entiendo que está pasando. Según yo lo que debería hacer es lo siguiente:

- por cada línea del archivo 1
- Verifica si contiene alguno de los caracteres del archivo2
- si es así pasa a la siguiente
- si no, entonces escribe la línea en el archivo

pero según el resultado no esta haciéndolo como yo quiero. Ojalá me puedan ayudar a entender esto.

De antemano GRACIAS
In a World without walls, who need Windows?
nrikex
Perlero nuevo
Perlero nuevo
 
Mensajes: 12
Registrado: 2006-09-15 15:11 @674

Publicidad

Notapor explorer » 2007-06-22 19:00 @833

Hay varios detalles...

* @archivo1 y @archivo2 no son archivos ni handles de archivos. Estás inicializándolos a un elemento cada uno de ellos: un string

* while (<@archivo1>) es la primera vez que lo veo en mi vida. He tenido que bucear en la documentación hasta encontrar la razón por la cual 'esto' 'funciona'. Por partes:
1.- No estás leyendo ningún archivo: @archivo1 no es handle de fichero, ni un typeglob ni una referencia a un typeglob ni un valor escalar (es un array de un solo elemento).
2.- Como es una operación de inicio de lista (hay un while) mostrando un valor en contexto escalar, lo que ocurre es que Perl hará un glob() de la expresión y nos irá devolviendo el siguiente fichero que coincida con el patrón indicado. Como lo indicado es un string compuesto de 'palabras' separadas por un espacio en blanco, el shell lo interpreta como entradas separadas (como si fueran líneas), por lo que, efectivamente, obtenemos las palabras dentro del bucle while como si cada una fuera una línea distinta, de un mismo fichero.

Bueno, todo este rollo para decir que el bucle primero funciona 'por auténtica casualidad', y que 'de ninguna manera' te recomiendo que lo sigas haciéndolo así.

* El programa no funciona por lo siguiente: en cada bucle de @archivo1, $i siempre vale lo mismo: 'bbb ccc', y ese es un patrón que no va a coincidir con ninguna de las entradas que nos devuelve <@archivo1>, por lo que siempre se ejecuta la parte de imprimir a ARCH3.

El mayor problema, para resolver lo planteado es cómo escribir en Perl la frase 'Verifica si contiene alguno de los caracteres del archivo2'. Tu lo planteas como un bucle dentro de otro: por cada palabra de @archivo1 lo buscas en el resto de @archivo2, pero, debemos saltar a la siguiente palabra si al menos coincide en alguna de las de @archivo2. El next que está puesto está afectando al bucle foreach, cuando en realidad debería estar afectando al while.

Esta es una de las muchas soluciones al problema:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
#!/usr/bin/perl
use strict;
use warnings;

my @archivo1 = qw(aaa bbb ccc ddd eee);
my @archivo2 = qw(bbb ccc);

BUCLE1:
foreach my $linea1 ( @archivo1 ) {
    foreach my $linea2 ( @archivo2 ) {
        next BUCLE1 if $linea1 =~ /$linea2/;
    }
    print "$linea1\n";
}

__OUTPUT__
aaa
ddd
eee
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4
Lo que hacemos es
* guardar en @archivo1 y @archivo2 varios elementos como si fueran líneas de dos ficheros distintos
* hacemos bucles foreach para recorrer todas esas líneas
* en el bucle más interior, se dice literalmente: "salta a la siguiente vuelta del PRIMER bucle si la línea del primer archivo coincide con algún patrón del segundo archivo". Se podía también haber escrito como:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
    if ( $linea1 =~ /$linea2/ ) {
        next BUCLE1;
    }
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

* si pasamos el bucle más interior, es que la $linea1 no coincide con nada de la 2, por lo que la pintamos.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14476
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Notapor nrikex » 2007-06-23 12:06 @546

Muchas Gracias, Explorer, no me había dado cuenta que:

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
@matriz = '1 2 3 4 5';
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


realmente solo genera una entrada y no cinco como erróneamente esperaba. Me queda claro el uso de qw(1 2 3 4 5) y ahora que lo entiendo mejor.

Y con respecto al 'next' me fue muy útil el uso de

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
next BUCLE1
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


sin embargo, ¿qué diferencia habría entre utilizar el 'next' en lugar del 'goto' o es lo mismo?

GRACIAS por tu pronta respuesta, me ha ayudado mucho.
In a World without walls, who need Windows?
nrikex
Perlero nuevo
Perlero nuevo
 
Mensajes: 12
Registrado: 2006-09-15 15:11 @674

Notapor explorer » 2007-06-23 12:29 @562

No, no es lo mismo... con next le decimos que haga la siguiente vuelta, pero con goto le decimos que salte a una nueva línea, con lo que comenzaría el bucle desde el principio.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14476
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Notapor nrikex » 2007-06-25 09:49 @451

Gracias por tus respuestas, me han ayudado mucho!
In a World without walls, who need Windows?
nrikex
Perlero nuevo
Perlero nuevo
 
Mensajes: 12
Registrado: 2006-09-15 15:11 @674


Volver a Básico

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 1 invitado