• Publicidad

Problema con HASH

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

Problema con HASH

Notapor Angelmoise » 2012-10-29 16:56 @747

Estimados:


Navegando por la web buscando solucionar un problema que tengo para crear un par de shell UNIX y manejar archivos con Perl, dado que el shell no me sirve para manejar grandes volúmenes de datos de un par de archivos planos.

Ahora bien, mi problema es el siguiente: Buscando aquí vi que hablan del termino hash. Entiendo que facilita la búsqueda de datos en un archivo. Pues bien mi problema es que tengo dos archivos; uno de 490 000 registros y otro de 290 000 registros; ambos tienen un campo común: teléfono más dos fechas separadas por ";". Debo extraer el teléfono del archivo 1 que se contenga en el archivo 2 y validar que la primera fecha del archivo 1 sea igual o mayor que la primera fecha del 2, y que la segunda fecha del primer archivo sea igual o mayor que la fecha del segundo archivo; si es así, grabo el teléfono en un archivo 3, cuyo resultado debe ser comparado con otros archivos que contiene números telefónicos.

Traté de implementar un ejemplo que saque de aquí pero no entendí cómo funciona el hash y cómo accedo a los elementos y cómo recorro el hash...

Les agradecería alguna orientación al respecto. Desde ya muchas gracias, mi versión de Perl es 5.8.4.

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2.  
  3. #use v5.8.4;
  4.  
  5. use POSIX qw(strftime);
  6.  
  7. #use autodie;
  8.  
  9. #recibe los archivos a procesar como parámetros 1 y 2 y el de salida3 en ARGV[0], [1], [2]
  10. #$archivoPPS=$ARGV[0];
  11.  
  12. #$arch448=ARGV[1]
  13. #$archInfoBc=ARGV[2]
  14.  
  15. $VarRuta = "/disk0/gesmdd/pareo/Bases/";
  16.  
  17. #open my $TMP448, '<', '/disk0/gesmdd/pareo/Bases/paso448.tmp';
  18. #open my $TMPBC, '<', '/disk0/gesmdd/pareo/Bases/pasobc.tmp';
  19. #open my $TMPANI, '>', '/disk0/gesmdd/pareo/Bases/pasoAni448.tmp';
  20.  
  21. open( TMP448, "/disk0/gesmdd/pareo/Bases/paso448.tmp" )    || print "paso448.tmp\n";
  22. open( TMPBC,  "/disk0/gesmdd/pareo/Bases/pasobc.tmp" )     || print "pasobc.tmp\n";
  23. open( TMPANI, "/disk0/gesmdd/pareo/Bases/pasoAni448.tmp" ) || print "pasoAni448.tmp\n";
  24.  
  25. # 1- Leemos el primer archivo, almacenando la información en el hash
  26. my %archivo1;
  27.  
  28. while ( my $linea = <$TMP448> ) {
  29.     chomp $linea;
  30.  
  31.     #  fono      FEC INI  FEC_FIN
  32.     my ( $campo1, $campo2, $campo3 ) = split( ";", $linea );
  33.     $archivo1{$campo1} =;
  34. }
  35.  
  36. # 2- Leemos el segundo archivo, comparando y grabando
  37. while ( my $linea = <$TMPBC> ) {
  38.     chomp $linea;
  39.     my ( $campo1, undef, $campo3 ) = split( ";", $linea, 4 );
  40.     if ( $archivo1{"$campo1"} ) {
  41.         printf( "%s;%s;%s", $campos[0], $TMP448{ $campos[0] }, $linea . "\n" );
  42.         say $TMPANI $linea;
  43.     }
  44. }
  45. close $TMP448;
  46. close $TMPBC;
  47. close $TMPANI;
Coloreado en 0.003 segundos, usando GeSHi 1.0.8.4



Como verán aquí no estoy controlando las fechas dado a que no entiendo cómo tomarlas desde los hash y aplicar la validación que requiero hacer...
Angelmoise
Perlero nuevo
Perlero nuevo
 
Mensajes: 6
Registrado: 2012-09-26 11:45 @531

Publicidad

Re: Problema con HASH

Notapor explorer » 2012-10-29 17:32 @772

¿Podrías publicar 4 o 5 líneas de cada uno de los archivos de texto?

No queremos ver datos reales, así que los números de teléfono y demás, los falseas. Las fechas y demás campos no sensibles, las puedes dejar, claro.

El código tiene un error sintáctico, en la línea 33. No hace falta mirar más para saber que no funciona...

La definición de un hash lo tienes en la Wikipedia.

En Perl, lo tienes un perldata.
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: Problema con HASH

Notapor Angelmoise » 2012-10-29 17:44 @780

Ok, aquí van los datos:

archivo 1
Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
72212511;20100127;99990101
73212511;20120412;99990101
71212512;20041019;99990101
51212513;20110428;99990101
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4


archivo 2
Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
72212510            ;20100125;20100213
72212511            ;20100125;20100213
72212512            ;20100125;20100213
72212513            ;20100125;20100213
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4


Debería sacar el 72212511
Angelmoise
Perlero nuevo
Perlero nuevo
 
Mensajes: 6
Registrado: 2012-09-26 11:45 @531

Re: Problema con HASH

Notapor explorer » 2012-10-29 18:32 @813

Vemos que es el archivo 2 el que contiene una relación única de teléfonos, mientras que es el archivo 1 el que puede contener repeticiones. Es en éste donde hay que hacer el filtrado.

Por eso primero leemos el archivo 2 y lo guardamos en memoria, en un hash, cuyas claves serán los números de teléfono, y sus valores serán un array con los dos valores de las fechas correspondientes a cada número de teléfono.

Luego, vamos leyendo el archivo 1, línea a línea, hacemos las comparaciones, y si se cumplen las reglas, sacamos fuera el número de teléfono.

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2. use v5.14;
  3.  
  4. # Leemos el archivo 2 y lo almacenamos en memoria
  5. my %telefonos;
  6.  
  7. open my $ARCHIVO2, '<', 'archivo2.csv' or die "ERROR: No puedo abrir archivo2.csv: $!\n";
  8.  
  9. while (<$ARCHIVO2>) {
  10.     chomp;                                      # quitamos el carácter de fin de línea
  11.  
  12.     my($telefono, @fechas) = split /\s*;\s*/;   # partimos la línea leída
  13.  
  14.     $telefonos{ $telefono } = [ @fechas ];      # almacenamos en la estructura. Es un hash de array
  15. }
  16.  
  17. close $ARCHIVO2;
  18.  
  19.  
  20. # Leemos el archivo 1 y lo procesamos
  21. open my $ARCHIVO1, '<', 'archivo1.csv' or die "ERROR: No puedo abrir archivo1.csv: $!\n";
  22.  
  23. while (<$ARCHIVO1>) {
  24.     chomp;
  25.  
  26.     my($telefono, @fechas) = split /\s*;\s*/;
  27.  
  28.     if ( exists $telefonos{ $telefono }                 # "el teléfono del archivo 1 que se contenga en el archivo 2"
  29.      and $fechas[0] >= $telefonos{ $telefono }[0]       # "validar que la primera fecha del archivo 1 sea igual o mayor que la primera fecha del 2"
  30.      and $fechas[1] >= $telefonos{ $telefono }[1]       # "la segunda fecha del archivo 1 sea igual o mayor que la fecha del archivo 2"
  31.     ) {
  32.         say $telefono;                                  # lo sacamos fuera
  33.     }
  34. }
  35.  
  36. close $ARCHIVO1;
  37.  
  38. __END__
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

Los hash son muy útiles porque nos relacionan informaciones a través de las claves.

Más información y ejemplos en perldsc.
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: Problema con HASH

Notapor Angelmoise » 2012-10-30 08:55 @413

Estimado:

Te agradezco mucho las ayuda de tu foro, ejecuté el script y apunté a los archivos que tenía que procesar y se demoró poquísimo, así es que el entusiasmo aumenta respecto de esta herramienta a tal punto que ahora voy por bases de datos y terminaré la parte final del proceso con el ejemplo de hash que me has dado. Nuevamente te agradezco muchísimo el apoyo que me has dado.

Finalmente solo me resta hacer una consulta. Yo puse en la función split():

split( ";", $linea)

y lo cambiaste por

split /\s*;\s*/;

¿Qué hacen estos símbolos: "/\s*" "\s*/" y cuál es la diferencia con ";"? ¿No es más legible ésta última?

Muy agradecido y saludos.

novato Perl
Angelmoise
Perlero nuevo
Perlero nuevo
 
Mensajes: 6
Registrado: 2012-09-26 11:45 @531

Re: Problema con HASH

Notapor explorer » 2012-10-30 10:50 @493

El ";" se refiere a que estás indicando que el delimitador de los campos es un carácter ';', pero en el segundo archivo estamos viendo que hay espacios en blanco a continuación del número de teléfono, y supongo que no quieres que formen parte del proceso de búsqueda.

Si no usáramos la expresión "\s*;\s*", entonces los espacios en blanco quedarían formando parte del número de teléfono:
Sintáxis: [ Descargar ] [ Ocultar ]
Using bash Syntax Highlighting
  1. > perl -E '$x = "ABC     ;CDF;FGH"; @x = split ";", $x; print "[$_]\n" for @x'
  2. [ABC     ]
  3. [CDF]
  4. [FGH]
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4


En cambio, indicando que el delimitador puede contener espacios en blanco, los estaremos quitando al hacer la división:
Sintáxis: [ Descargar ] [ Ocultar ]
Using bash Syntax Highlighting
  1. > perl -E '$x = "ABC     ;CDF;FGH"; @x = split /\s*;\s*/, $x; print "[$_]\n" for @x'
  2. [ABC]
  3. [CDF]
  4. [FGH]
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


Más información en perldoc -f split
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: Problema con HASH

Notapor Angelmoise » 2012-10-30 16:26 @726

Entiendo. Gracias por responder. Ahora bien, dónde puedo encontrar toda esa simbología que abarca la función split(), y finalmente mi última duda es saber si el hash trabaja como par ordenado, entonces ¿qué pasa si solo tengo que manejar un solo dato? Por ejemplo, para el ejemplo adjunto el teléfono solamente y no las fechas. ¿cómo se crea el indice del hash? y ¿cómo sería la sintaxis ya que es un solo dato?


¿Quedaría así?

# Leemos el archivo 2 y lo almacenamos en memoria
my %telefonos;
open my $ARCHIVO2, '<', 'archivo2.csv' or die "ERROR: No puedo abrir archivo2.csv: $!\n";
while (<$ARCHIVO2>) {
chomp;
my($telefono);
telefonos{ $telefono };
}
close $ARCHIVO2;

Saludos y de antemano. Gracias.
Angelmoise
Perlero nuevo
Perlero nuevo
 
Mensajes: 6
Registrado: 2012-09-26 11:45 @531

Re: Problema con HASH

Notapor explorer » 2012-10-30 16:45 @740

Angelmoise escribiste:Ahora bien, dónde puedo encontrar toda esa simbología que abarca la función split()

Ya te lo he indicado antes, pero te lo amplío:
  • en tu propio ordenador: ejecuta perldoc -f split (en inglés)
  • en la web: split (en inglés)
  • traducido: en el documento perlfunc, busca por la sección de split


Angelmoise escribiste:mi última duda es saber si el hash trabaja como par ordenado, entonces ¿qué pasa si solo tengo que manejar un solo dato? Por ejemplo, para el ejemplo adjunto el teléfono solamente y no las fechas. ¿cómo se crea el indice del hash? y ¿cómo sería la sintaxis ya que es un solo dato?

Si solo vamos a guardar un dato, se podría meter en un array,

push @telefonos, $telefono;

o con un hash, así:

$telefonos{ $telefono } = 1;

Más información en tu propio ordenador en perldoc perldsc, y en la Web (traducido).
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


Volver a Básico

¿Quién está conectado?

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