Perl en Español

  1. Home
  2. Tutoriales
  3. Foro
  4. Artículos
  5. Donativos
  6. Publicidad
 

Cómo puedo filtrar algunas llaves en un hash

 
Publicar nuevo tema   Responder al tema    Foros de discusión -> Experto
Mensaje Mar May 06, 2008 11:24 am
rsanchez
Perlero Nuevo
Perlero Nuevo
Registrado: 06 May 2008
Mensajes: 3
Cómo puedo filtrar algunas llaves en un hash Responder citando

Hola a todos,

Tengo un problema para poder filtrar por llaves de un hash, espero poder expresar bien mi duda.

Estos son los datos del archivo alumnos.dat (IDSALON, IDGRADO, IDALUMNO, NOLISTA, NOMBRE)

    1=A=6=14=Juan Perez
    1=B=12=9=Carlos Buenrostro
    1=C=24=33=Maria de las Nieves
    2=A=19=22=Adalberto Madero
    2=B=31=14=Maria Felix
    3=A=27=11=Guadalupe Victoria


y este es el código en Perl
Perl:
#!/usr/bin/perl -w
#

use strict;
use Lib::DB::DBFile;
use Lib::DB::DBConnect;

my(%filtalumnos,%db_data,@alumnos,$alumnos, $dbh,$sth);
my $DBFile = new Lib::DBFile::DBFile;
my $qry = qq/select  IDSALON, IDGRADO, IDALUMNO, NOLISTA, NOMBRE from ALUMNOS/;

@alumnos = $DBFile->dbopen("alumnos.dat");
$dbh = DBConnect->connect();
$sth = $dbh->prepare($qry) or die("No se puede preparar: $qry" . $dbh->errstr);
$sth->execute() or die("No se puede ejecutar: $qry" . $sth->errstr);
chomp @alumnos;

%db_data = map {$_->[0].@$_[2], join("=",  @$_)}
        @{$dbh->selectall_arrayref($qry)};
$sth = $dbh->prepare($qry) or die("No se puede preparar: $qry" . $dbh->errstr);
$sth->execute() or die("No se puede ejecutar: $qry" . $sth->errstr);

foreach $alumnos (@alumnos){
        my @data=split(/=/,$alumnos,-1);
}

exit(0);


Ahora explico el script.

1.- Se crea una variable @alumnos con los registros del archivo alumnos.
2.- Se obtienen todos los registro de la DB de los alumnos.
3.- Se crea un hash %db_data usando como llave el IDSALON y IDALUMNO
4.- Se validan los alumnos del archivo dentro del foreach.

En este último punto es donde no sé cómo crear un filtro del HASH, es decir, al leer el primer registro puedo determinar que el IDSALON es igual a 1 pero quiero filtrar el hash %db_data y crear un nuevo hash %filtalumnos donde estén solamente las llaves que tengan IDSALON = 1 independientemente del IDALUMNO.

Una vez filtrado si el alumno está en el nuevo hash filtrado será borrado
Perl:
delete %filtalumnos{$alumno[0].$alumno[2]}


Al continuar con el foreach en el registro 4 el IDSALON cambia a 2 y los alumnos que estén el hash filtrado son los que no están en clase así que se marcan con falta.

Y se repite el proceso para el IDSALON = 2.

Espero haberme explicado bien en cuanto al problema que tengo y que me puedan ayudar a solucionarlo.


Saludos y Gracias.
Mensaje Mar May 06, 2008 11:59 am
explorer
Moderador
Moderador
Registrado: 24 Jul 2005
Mensajes: 4092
Ubicación: Valladolid, España
Responder citando

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

Si suponemos que IDSALON solo consta de un dígito, puedes filtrar las claves de %db_data por ese primer dígito:

Perl:
%filtalumnos = ();
for my $clave ( keys %db_data ) {
    $filtaalumnos{$clave} = $db_data{$clave}
        if $clave =~ /^$data[0]/;
}
Mensaje Mar May 06, 2008 4:18 pm
rsanchez
Perlero Nuevo
Perlero Nuevo
Registrado: 06 May 2008
Mensajes: 3
Gracias por la ayuda lo he solucionado. Responder citando

Explorer, Muchas Gracias...

Tal vez estaba tratando de hacer las cosas más complicadas con la función map.

Con el dato que me proporcionaste me ayudaste a solucionar el problema, solo que IDSALON sí puede ser mayor a 2 dígitos por lo que realice un cambio y quedo así.

Perl:
%filtalumnos = ();
for my $clave ( keys %db_data ) {
    my @newdat = split(/=/,$db_data{$clave});
    $filtaalumnos{$clave} = $db_data{$clave}
        if $newdat[0] == $data[0];
}


Nuevamente muchas gracias y felicidades a este excelente foro.
Mensaje Mar May 06, 2008 5:15 pm
explorer
Moderador
Moderador
Registrado: 24 Jul 2005
Mensajes: 4092
Ubicación: Valladolid, España
Responder citando

En esos casos, lo normal es separar las dos claves de la clave hash con un carácter separador, para que sea fácil luego extraerlos.

Esta es otra forma:

Perl:
%filtaalumnos = ();
while ( my ($clave, $valor) = each %db_data ) {
    $filtaalumnos{$clave} = $valor
        if $data[0] == (split '=', $valor, 2)[0];
}


De todas formas, yo miraría de hacerlo de otra manera, usando una dimensión más con un hash o array, para evitar tener que usar claves compuestas.
Mensaje Mar May 06, 2008 5:55 pm
rsanchez
Perlero Nuevo
Perlero Nuevo
Registrado: 06 May 2008
Mensajes: 3
Responder citando

Explorer,

Tendría que checar los cambios que tengo que hacer para que el hash sea dimensionado.

Pero ¿crees que sería más eficiente así o funcionaria igual que como está ahora?

Esto dado que la cantidad de registros son muchos y puede demorar algún tiempo, por eso busco la mejor manera de hacer esto.

Saludos.
Publicar nuevo tema   Responder al tema    Foros de discusión -> Experto Todas las horas son GMT - 6 Horas
Página 1 de 1



Powered by phpBB © 2001, 2005 phpBB Group