• Publicidad

Comparar dos columnas de archivos diferentes

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

Comparar dos columnas de archivos diferentes

Notapor Lugerius » 2008-07-12 12:31 @563

¡Saludos a todos desde México!

Estoy empezando con Perl y estoy batallando mucho con este programita. :roll:
Tengo dos archivos de texto con el siguiente formato,
Archivo1.txt
Código: Seleccionar todo
AC000000000   0   0
AC100000000   0   0
AC1100KLP00   19   51.72
AC3030GEN15   7   30.91
AC4015GEN04   11   4.83
AC4017GEN04   0   4.41
AC4017GEN05   24   5.54
AC5001GEN05   66   6.68
AC5002FPC09   15   28.78
AC5002GEN05   16   8.88
AC5003GEN00   6   6.11
AC700000000   0   0


Archivo2.txt
Código: Seleccionar todo
AC1100KLP00   761.91   19
AC1300GEN06   #N/A    #N/A
AC2100GEN05   #N/A           #N/A
AC3030GEN15   49.77   7
AC3030GEN60   #N/A           #N/A
AC4015GEN04   81.65   12
AC4017GEN04   #N/A           #N/A
AC4017GEN05   93.65   24
AC5001GEN05   10.75   23


Lo que quiero que el programa haga es que cada uno de los elementos de la columna 1 del archivo1.txt se compare con todos los elementos de la columna 1 del archivo2.txt y cuando sean iguales escribir en un nuevo archivo3.txt el contenido de esas filas del archivo1.txt. Espero haberme explicado.

Es decir, en mi ejemplo el archivo3.txt debería quedar más o menos así:
Código: Seleccionar todo
AC1100KLP00   19   51.72
AC3030GEN15   7   30.91
AC4015GEN04   11   4.83
AC4017GEN04   0   4.41
AC4017GEN05   24   5.54
AC5001GEN05   66   6.68


Donde tengo la duda principalmente es en el algoritmo para comparar los elementos de las columnas 1 de los dos archivos.

No pongo código porque estoy bastante perdido en este asunto, no sé si con un while o metiendo las columnas en arreglos y con foreach, pero he intentado varias cosas y no obtengo los resultados esperados.

De este mismo foro, leí que podía pegar mis archivos en uno solo con el comando paste, pero aún así no sé cómo comparar completamente las dos columnas.

Espero puedan ayudarme y de antemano ¡gracias!

Atte.
Luis G. Mendoza
Lugerius
Perlero nuevo
Perlero nuevo
 
Mensajes: 5
Registrado: 2008-07-12 11:44 @530

Publicidad

Notapor explorer » 2008-07-12 13:06 @587

Bienvenido a los foros de Perl en Español, Lugerius.

Pues tienes razón. Con un while y un hash, tienes solucionado el problema.

Si pones el código te podemos ir dando más pistas.

Aquí te pongo la solución, en forma de pseudocódigo.

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

# Leemos el fichero Archivo2 y almacenamos la primera columna como claves
# Abrimos los ficheros Archivo1 en lectura y Archivo3 en escritura
# Para todas las líneas de Archivo1
# Si la primera columna de Archivo1 está entre las claves de Archivo2
#   Escribimos la línea de Archivo1 en el Archivo3
# Fin del bucle
# Cerramos los archivos abiertos
Coloreado en 0.002 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

Notapor Lugerius » 2008-07-12 13:27 @602

Muchas gracias por tu ayuda, voy a leer un poco más sobre los hash y en cuanto tenga el código lo publico.

¡SALUDOS!

Atte.
Luis G. Mendoza
Lugerius
Perlero nuevo
Perlero nuevo
 
Mensajes: 5
Registrado: 2008-07-12 11:44 @530

Otra cosa

Notapor Lugerius » 2008-07-12 17:51 @785

Bueno ya funciona el script pero me parece que no es la mejor forma de hacerlo, de todas formas aquí pongo el código.

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
# Leemos el fichero Archivo2 y almacenamos la primera columna como claves
open(ORIG,"archivo2.txt");
our %hash = ();
our $elemento;
while ($elemento=<ORIG>){
chomp($elemento);
my @linea = (split "\t",$elemento);
$hash{$linea[0]} = 1;
}  
# Abrimos los ficheros Archivo1 en lectura y Archivo3 en escritura
open(DATOS,"archivo1.txt");
open(OUT,">archivo3.csv");
# Para todas las líneas de Archivo1
while (my $lineas=<DATOS>) {
        chomp($lineas);
        our $col1 = (split "\t",$lineas)[0];
        foreach my $llave (keys %hash){
# Si la primera columna de Archivo1 está entre las claves de Archivo2
                if ($col1 eq $llave) {
#   Escribimos la línea de Archivo1 en el Archivo3
                print OUT "$lineas\n";
                        }
# esta parte es la que no me queda...
                else { print "$elemento"; }
                }
               
}
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


Lo que quiero agregar es esto último
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
#   Escribimos la línea de Archivo1 en el Archivo3
                print OUT "$lineas\n";
                        }
# esta parte es la que no me queda...
                else { print "$elemento"; }
                }
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


Ahora quiero que una vez que haya agregado todas las líneas correspondientes del archivo1.txt al archivo3.csv, las líneas que están en el archivo2.txt y que no encontró en archivo1.txt se impriman en el archivo3.txt con el formato:

Código: Seleccionar todo
AC1100KLP00   0   0


para que quede más o menos así:

Código: Seleccionar todo
AC1100KLP00   19   51.72
AC1300GEN06   0   0
AC2100GEN05   0   0
AC3030GEN15  7   30.91
AC3030GEN60   0   0
AC4015GEN04   11   4.83
AC4017GEN04   0   4.41
AC4017GEN05   24   5.54
AC5001GEN05   66   6.68


Espero su ayuda, ya estuve dándole vueltas a esto y no he podido completarlo.

De antemano ¡Gracias!
Atte.

Luis G. Mendoza
Lugerius
Perlero nuevo
Perlero nuevo
 
Mensajes: 5
Registrado: 2008-07-12 11:44 @530

Notapor explorer » 2008-07-12 18:36 @817

Enhorabuena. Has conseguido resolver el primer problema.

Lo único, comentarte que los hash se suelen usar para 'recordar' cosas (por algo, también se les llama memoria asociativas). Así que se puede usar de otra forma más inteligente.

Aquí está mi solución.
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
#!/usr/bin/perl
use strict;
use warnings;
use diagnostics;

# Leemos el fichero Archivo2 y almacenamos la primera columna como claves
my %archivo2;

open(FICHERO2, '<Archivo2.txt') or die "$!\n";
while ( my $linea = <FICHERO2> ) {
    my ($columna1) = split(" ", $linea);
    $archivo2{$columna1} = $linea;
}
close(FICHERO2);

# Abrimos los ficheros Archivo1 en lectura y Archivo3 en escritura
open(FICHERO1, '<Archivo1.txt') or die "$!\n";
open(FICHERO3, '>Archivo3.txt') or die "$!\n";

# Para todas las líneas de Archivo1
while ( my $linea = <FICHERO1> ) {

    # Si la primera columna de Archivo1 está entre las claves de Archivo2
    my ($columna1) = split(" ", $linea);
    if ( $archivo2{$columna1} ) {

        # Escribimos la línea de Archivo1 en el Archivo3
        print FICHERO3 $linea;

        # Borramos la clave de Archivo2
        delete $archivo2{$columna1};
    }
}

# Escribimos las líneas de Archivo2 que no se imprimieron
foreach my $clave ( keys %archivo2 ) {
    print FICHERO3 "$clave   0   0\n";
}

# Cerramos los archivos abiertos
close(FICHERO1);
close(FICHERO3);
Coloreado en 0.002 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

Gracias, es exactamente lo que necesito

Notapor Lugerius » 2008-07-14 11:12 @508

Gracias, es exactamente lo que necesito, ahora voy a seguir agregando funciones a mi script, la solución que pusiste me despejó varias dudas que tenía con el hash y otras cosas, de todos modos creo que necesito un buen libro de Perl, apenas estoy descubriendo su potencia.

¡Saludos y muchas gracias!

Atte.

Luis G. Mendoza
Lugerius
Perlero nuevo
Perlero nuevo
 
Mensajes: 5
Registrado: 2008-07-12 11:44 @530


Volver a Básico

¿Quién está conectado?

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

cron