• Publicidad

Comparar y aprovechar información de dos ficheros

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

Comparar y aprovechar información de dos ficheros

Notapor boteropepe » 2010-11-11 07:55 @371

Hola, tengo un problema para comparar y aprovechar dos ficheros, que son de este tipo:

FICHERO A:
Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
elena   lópez   madre
juan    gómez   padre   situación:casado
luis    lópez   abuelo  situación:casado
luis    gómez   hijo    situación:soltero       mayoría:sí
ana     gómez   hija    situación:nonato
ana     lópez   tía     situación:divorciado
pablo   ruiz    amigo
claudia gómez   hermana situación:divorciado
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4


FICHERO B:
Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
elena   lópez   madre   situación:casado
juan    gómez   padre   situación:casado
luis    lópez   abuelo  situación:viudo
luis    gómez   hijo    situación:soltero       mayoría:sí
ana     gómez   hija    mayoría:no
ana     lópez   tía
laura   garcía  tía
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4


El fichero A es mucho más extenso que el B (se podría decir que A es más general y B más específico); por otro lado, B es el que contiene la información actualizada. Lo que querría es guardar la información del fichero B completa, y solo las líneas de A que contengan 'situación:' o 'mayoría:'.

Dicho de otra manera: quiero hacer un nuevo fichero con toda la información posible para todos los elementos de B y para los elementos de A cuya situación o mayoría queden especificadas, y lo que no quiero es que haya líneas con nombres, apellidos y lugar que ocupan en la familia repetidos (si en B no aparecen la situación y/o la mayoría, que éstas se copien de A; si en A aparecen valores diferentes para esos campos, que se copie solo la línea correspondiente de B y se descarte la de A).

Espero que se me entienda. Hasta ahora he conseguido hacer todo lo que quería, menos eliminar las líneas idénticas a otras con menos información (por ejemplo, entre 'ana lópez tía situación:divorciado' de A y 'ana lópez tía' de B, solo querría que apareciera la línea del fichero A).

Si alguien me puede ayudar, lo agradezco de veras.
Última edición por boteropepe el 2010-11-16 11:21 @514, editado 1 vez en total
boteropepe
Perlero nuevo
Perlero nuevo
 
Mensajes: 18
Registrado: 2010-03-08 15:14 @676

Publicidad

Re: Comparar y aprovechar información de dos ficheros

Notapor explorer » 2010-11-11 08:45 @406

Yo primero leería todo el fichero A en memoria, guardándolo en un hash, siendo las claves el texto que forma las tres primeras columnas. Y el valor sería el resto de la línea.

Luego, abriría el fichero B, y lo leería línea a línea.

Por cada línea, hago lo mismo: separo las tres primeras columnas del resto. Las tres primeras serán la clave, y el resto, el valor.

Luego, miro a ver si existe la clave en el hash del fichero A. Si no existe, es que es una línea nueva, así que creo una nueva entrada en el hash, con esa clave y valor.

Si existe, solo tengo que comparar la longitud del valor con el valor de la correspondiente entrada del hash. Según sea mayor o menor, sobreescribiré la entrada del hash.

Terminado de leer el fichero B, solo queda crear el contenido resultado, sacándolo de forma ordenada desde el hash.
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: Comparar y aprovechar información de dos ficheros

Notapor boteropepe » 2010-11-16 05:30 @270

Muchas gracias. Llevo intentando un tiempo hacerlo como me has dicho, explorer, pero al querer imprimir la información del hash me encuentro con un problema que no sé cómo se resuelve; he comprobado otros programas antiguos y por lo menos la sintaxis utilizada para imprimir la clave y el valor no están mal (he probado a hacerlo de varias maneras, con foreach(), con while() y después each()... y siempre tengo el mismo problema), o eso creo yo, así que debe de ser otra cosa.

Copio aquí parte del programa, por si alguien me puede decir dónde estoy metiendo la pata:

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2.  
  3. use strict;
  4. use locale;
  5.  
  6. my %family_1;
  7. my %family_2;
  8.  
  9. open (FILE_1, "$ARGV[0]") || die ("falta fichero argumento 1");
  10.  
  11.    while (<FILE_1>) {
  12.  
  13.       chomp;
  14.  
  15.       my @list = split (/\t/, $_);
  16.  
  17.       my $relative = "$list[0]\t$list[1]\t$list[2]";
  18.  
  19.       my $info;
  20.  
  21.       if ($list[3] =~ /./) {
  22.          if ($list[4] =~ /./) {            $info = "$list[3]\t$list[4]";
  23.          } else {
  24.             $info = "$list[3]";
  25.          }
  26.       }
  27.  
  28.       push (@{$family_1{$relative}}, $info);
  29.  
  30.    }
  31.  
  32. close FILE_1;
  33.  
  34. foreach my $key (sort keys %family_1) {
  35.    print "$key\t$family_1{$key}\n";
  36. }
Coloreado en 0.003 segundos, usando GeSHi 1.0.8.4



El problema hasta ahí es que los valores no se me imprimen, sino que el resultado es este:

Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
ana     gómez  hija    ARRAY(0x9ef7b80)
ana     lópez  tía    ARRAY(0x9f02980)
claudia gómez  hermana ARRAY(0x9ef79f0)
elena   lópez  madre   ARRAY(0x9ed9968)
juan    gómez  padre   ARRAY(0x9ef7000)
luis    gómez  hijo    ARRAY(0x9f02a00)
luis    lópez  abuelo  ARRAY(0x9f029d0)
pablo   ruiz    amigo   ARRAY(0x9ef7a30)
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4


A ver si alguien me puede ayudar; la manera de dividir la línea en $relative y $info es una de tantas que he probado (pero como he visto que no influye en los resultados, he dejado sin más la última que probé, que puede no ser la mejor).

Gracias de antemano.
boteropepe
Perlero nuevo
Perlero nuevo
 
Mensajes: 18
Registrado: 2010-03-08 15:14 @676

Re: Comparar y aprovechar información de dos ficheros

Notapor explorer » 2010-11-16 05:59 @291

El problema es que estás

push (@{$family_1{$relative}}, $info);

guardando la información $info como un elemento de un array, como valor del hash. Es decir, estás creando un hash de array. Por eso, en la salida, lo que obtienes es ARRAY(0x...). Perl te dice que estás intentando imprimir un array como si fuera un escalar.

Debería bastarte con

$family_1{$relative} = $info;

Así, estás guardando la $info asociada a $relative, como un simple escalar.

Lo que te falta es la parte de comparar la $info anterior, para la misma clave $relative.
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: Comparar y aprovechar información de dos ficheros

Notapor boteropepe » 2010-11-16 06:16 @303

Esto me pasa por copiar directamente cosas "útiles" de programas anteriores, sin pararme a mirar. Seguro que solo no lo veo ni en 100 años, muchas gracias de nuevo. Ahora mismo sigo con esto, a ver.
boteropepe
Perlero nuevo
Perlero nuevo
 
Mensajes: 18
Registrado: 2010-03-08 15:14 @676

Re: Comparar y aprovechar información de dos ficheros

Notapor boteropepe » 2010-11-16 06:59 @332

Bueno, ahora ya creo que me sale todo como quería:

FICHERO 1
Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
ana     gómez   hija    situación:nonato
ana     lópez   tía     situación:divorciado
claudia gómez   hermana situación:divorciado
elena   lópez   madre
juan    gómez   padre   situación:casado
luis    gómez   hijo    situación:soltero       mayoría:sí
luis    lópez   abuelo  situación:casado
pablo   ruiz    amigo
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4


FICHERO 2
Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
ana     gómez   hija    mayoría:no
ana     lópez   tía
elena   lópez   madre   situación:casado
juan    gómez   padre   situación:casado
laura   garcía  tía
luis    gómez   hijo    situación:soltero       mayoría:sí
luis    lópez   abuelo  situación:viudo
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4


PROGRAMA:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2.  
  3. use strict;
  4. use locale;
  5. # use utf8;
  6.  
  7. my %family_1;
  8. my %family_2;
  9.  
  10. open (FILE_1, "$ARGV[0]") || die ("falta fichero argumento 1");
  11.  
  12.    while (<FILE_1>) {
  13.  
  14.       chomp;
  15.       my @list = split (/\t/, $_);
  16.       my $relative = "$list[0]\t$list[1]\t$list[2]";
  17.       my $info;
  18.  
  19.       if ($list[3] =~ /./) {
  20.          if ($list[4] =~ /./) {
  21.             $info = "$list[3]\t$list[4]";
  22.          } else {
  23.             $info = "$list[3]";
  24.          }
  25.       }
  26.  
  27.       $family_1{$relative} = $info;
  28.  
  29.    }
  30.  
  31. close FILE_1;
  32.  
  33. open (FILE_2, "$ARGV[1]") || die ("falta fichero argumento 2");
  34.  
  35.    while (<FILE_2>) {
  36.  
  37.       chomp;
  38.       my @list = split (/\t/, $_);
  39.       my $relative = "$list[0]\t$list[1]\t$list[2]";
  40.       my $info;
  41.  
  42.       if ($list[3] =~ /./) {
  43.          if ($list[4] =~ /./) {
  44.             $info = "$list[3]\t$list[4]";
  45.          } else {
  46.             $info = "$list[3]";
  47.          }
  48.       }
  49.  
  50.       ($family_2{$relative} = $info) unless exists $family_1{$relative};   # escribe en el hash las entradas que solo aparecen en el fichero 2
  51.  
  52.       if (exists $family_1{$relative}) {   # para entradas en ambos ficheros
  53.  
  54.          if (($info =~ /^$/) & ($family_1{$relative} =~ /.+/)) {
  55.             $family_2{$relative} = $family_1{$relative};   # escribe $info del fichero 1 si en el fichero 2 no hay $info
  56.          } else {
  57.             $family_2{$relative} = $info;   # en el resto de los casos, escribe siempre $relative y $info del fichero 2
  58.          }
  59.       }   }
  60.  
  61. close FILE_2;
  62.  
  63. foreach my $key (sort keys %family_2) {
  64.  
  65.    if ($family_2{$key} =~ /^$/) {       # casos en los que no hay $info
  66.       print "$key\n";
  67.    } else {                             # casos en los que hay $info
  68.       print "$key\t$family_2{$key}\n";
  69.    }
  70. }
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4



TEXTO RESULTANTE:
Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
ana     gómez  hija    mayoría:no
ana     lópez  tía    situación:divorciado
elena   lópez  madre   situación:casado
juan    gómez  padre   situación:casado
laura   garcía tía
luis    gómez  hijo    situación:soltero      mayoría:sí
luis    lópez  abuelo  situación:viudo
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4



Cualquier comentario se acepta, por supuesto. Siempre digo lo mismo, pero muchas gracias por la ayuda y por la rapidez.
boteropepe
Perlero nuevo
Perlero nuevo
 
Mensajes: 18
Registrado: 2010-03-08 15:14 @676

Re: Comparar y aprovechar información de dos ficheros

Notapor explorer » 2010-11-16 09:23 @432

Hay un problema con la descripción del problema...

En el primer mensaje dices que quieres quedarte con la línea más larga de los dos ficheros, para la misma persona, en el caso de que en los dos ficheros esa persona tenga informaciones distintas.

Pero a continuación, dices que prefieres, en esa situación, siempre quedarte con la información del primer fichero. Y esa es la solución que resuelve el programa.

¿Estás seguro de que está bien, y lo que sobra es lo de "la línea más larga"?
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: Comparar y aprovechar información de dos ficheros

Notapor boteropepe » 2010-11-16 10:01 @459

Tienes razón, me equivoqué al describir el problema (también es la tercera vez que escribo este mensaje, me he hecho un lío).

Creo que sobre todo es que he invertido el orden en que se pasan los ficheros al programa (al principio era primero el más específico y actual, y después el más extenso y antiguo; ahora es justo al revés).

Por otro lado, interesa solo guardar la información del fichero más actual en caso de conflicto (del abuelo, por ejemplo, si solo se tomara la línea más extensa se guardaría 'casado' en lugar de 'viudo'). Siento el lío, pero muchas gracias por poner tanta atención en los problemas.
boteropepe
Perlero nuevo
Perlero nuevo
 
Mensajes: 18
Registrado: 2010-03-08 15:14 @676

Re: Comparar y aprovechar información de dos ficheros

Notapor explorer » 2010-11-16 10:59 @499

Ya sé que sería algo muy aburrido, pero estaría genial que pudieras reeditar el primer mensaje, con la descripción correcta. Te lo pido porque mucha gente que está aprendiendo Perl usa estos foros para practicar: leen la pregunta e intentan resolverlo por su cuenta. Algo así como unos ejercicios de clase. Si les facilitamos la tarea de entender bien el problema desde el principio, sería estupendo.

Ahora agregas un detalle más, que es el que define qué fichero elegir: si el más moderno o el más antiguo.

El botón de editar el mensaje lo tienes abajo a la derecha, en cada mensaje publicado.

Ya me ocuparé, luego, de reeditar el resto del hilo.
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: Comparar y aprovechar información de dos ficheros

Notapor boteropepe » 2010-11-16 11:23 @516

Es verdad, mejor dejarlo bien desde el principio. Creo que ya está (si no es así, lo corregiré; si es así, borraré después este mensaje).
boteropepe
Perlero nuevo
Perlero nuevo
 
Mensajes: 18
Registrado: 2010-03-08 15:14 @676


Volver a Básico

¿Quién está conectado?

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