• Publicidad

Cómo puedo filtrar algunas llaves en un hash

Así que programas sin strict y las expresiones regulares son otro modo de hablar. Aquí encontrarás respuestas de nivel avanzado, no recomendable para los débiles de corazón.

Cómo puedo filtrar algunas llaves en un hash

Notapor rsanchez » 2008-05-06 12:24 @558

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)

[listbc]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[/list:ubc]

y este es el código en Perl
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
#!/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);
Coloreado en 0.003 segundos, usando GeSHi 1.0.8.4


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
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
delete %filtalumnos{$alumno[0].$alumno[2]}
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


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.
rsanchez
Perlero nuevo
Perlero nuevo
 
Mensajes: 3
Registrado: 2008-05-06 10:58 @498

Publicidad

Notapor explorer » 2008-05-06 12:59 @583

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:

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
%filtalumnos = ();
for my $clave ( keys %db_data ) {
    $filtaalumnos{$clave} = $db_data{$clave}
        if $clave =~ /^$data[0]/;
}
Coloreado en 0.001 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 por la ayuda lo he solucionado.

Notapor rsanchez » 2008-05-06 17:18 @762

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í.

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
%filtalumnos = ();
for my $clave ( keys %db_data ) {
    my @newdat = split(/=/,$db_data{$clave});
    $filtaalumnos{$clave} = $db_data{$clave}
        if $newdat[0] == $data[0];
}
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


Nuevamente muchas gracias y felicidades a este excelente foro.
rsanchez
Perlero nuevo
Perlero nuevo
 
Mensajes: 3
Registrado: 2008-05-06 10:58 @498

Notapor explorer » 2008-05-06 18:15 @802

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:

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
%filtaalumnos = ();
while ( my ($clave, $valor) = each %db_data ) {
    $filtaalumnos{$clave} = $valor
        if $data[0] == (split '=', $valor, 2)[0];
}
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


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.
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 rsanchez » 2008-05-06 18:55 @830

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.
rsanchez
Perlero nuevo
Perlero nuevo
 
Mensajes: 3
Registrado: 2008-05-06 10:58 @498


Volver a Avanzado

¿Quién está conectado?

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

cron