• Publicidad

Arreglo de Hashes

¿Ya sabes lo que es una referencia? Has progresado, el nível básico es cosa del pasado y ahora estás listo para el siguiente nivel.

Arreglo de Hashes

Notapor RWing » 2009-06-12 21:48 @950

Hola a todos, estoy teniendo un pequeño problema tratando de acceder a una tabla hash.

Bueno, aquí van las preguntas:

1- ¿Puedo almacenar un hash dentro de un arreglo?
2- En caso de que sí, ¿accedo de la misma forma como si fuera un arreglo normal y un hash normal?

Aquí está parte del código que estoy utilizando:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
sub creaDiccionario
{      
        $punteroActual = 0;
        #terminosGeneral es un hash con llave->palabra y valor->IDPalabra
        foreach $palabra (sort keys %terminosGeneral)
        {                      
                $veces = 0;
                #@paraPosting es el arreglo de hashes
                foreach $palabraDoc (@paraPostings)
                {
                        #utilizo el hash como si se cargara en la variable $palabraDoc y pregunto si existe la llave $palabra
                        if (exists ($palabraDoc{$palabra}))
                        {
                                $veces ++;
                        }
                }
                print {$diccionarioFile} $palabra . " " . $punteroActual . " " . $veces . "\n";
                $punteroActual = $punteroActual + $veces;
        }
       
}
Coloreado en 0.003 segundos, usando GeSHi 1.0.8.4


Espero que alguien me pueda guiar un poco...

Gracias.

---
Ricardo Wing Alcázar
ClearCorp
www.clearcore.co.cr
RWing
Perlero nuevo
Perlero nuevo
 
Mensajes: 3
Registrado: 2009-06-12 18:36 @817

Publicidad

Notapor explorer » 2009-06-13 05:05 @253

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

1.- Puedes almacenar un diccionario dentro de un arreglo, guardando los pares clave/valor como elementos individuales del arreglo. O también, puedes guardar el diccionario entero como una referencia en uno de los elementos del arreglo, que parece ser esto último lo que estás usando, atendiendo a los comentarios del código.

2.- El acceso a los datos debe ser un reflejo de la estructura de datos que tengas.

Según el código presentado, habría que hacer unos cambios:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
$palabraDoc{$palabra}
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

por
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
$palabraDoc->{$palabra}
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

Si $palabraDoc contiene un elemento de un arreglo de diccionarios, es lo mismo que decir que contiene realmente una referencia a un diccionario. Y la forma de des-referenciarlo es con el '->'.

En caso de duda, usa Data::Dumper:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
use Data::Dumper;
print Dumper \@paraPostings;
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: 14486
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Notapor RWing » 2009-06-13 12:04 @544

Hola, muchas gracias por la pronta respuesta. Ahora sí lo está haciendo bien, pero tengo un pequeño problema con referencias.

Necesito que el hash se vacíe y que se vuelva a llenar en un ciclo. Entonces lo que hago es hacerle un undef(). Lo que pasa es que esto me anula TODOS los hash que se van creando y agregando al arreglo porque guarda una referencia a ese hash.

¿No existe alguna forma de que el hash sea creado nuevamente sin que afecte el hash anterior?

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
find(\&archivo, $dir);

sub archivo
{      
#...

#Aqui leo archivos HTML obtengo las referencias y los tags
#Quito todas las mayusculas y las paso a minusculas
#quito todas las tildes y conservo las ñ

#...

                foreach $palabra (@palabras)
                {
                        $palabra =~ s/[^a-z0-9_\-]*([a-z0-9_\-]*)[^a-z0-9_\-]*/$1/g;
                        #si no es un stopword
                        if (not(exists($stop{$palabra})))
                        {
                                #la agrega al hash si no exite con cuenta en 1, si ya existe le suma uno a la cuenta
                                $apareceEnDoc{$palabra}++;
                                #agrega la palabra a una tira con todos los documentos unidos para el arreglo de sufijos
                                $todoTira = $todoTira . " " . $palabra;
                                #si no existe en los términos entonces lo agrega y le asigna un ID
                                if (not exists $terminosGeneral{$palabra})
                                {
                                        $terminosGeneral{$palabra}=$termID;
                                        print {$termFile} $termID . " " . $palabra . "\n";
                                        $termID ++;
                                }
                        }
                }
#agrega el hash con los terminos y sus fercuencias a un arreglo para la obtener el posting mas adelante
                push(@paraPostings, \%apareceEnDoc);
.
.
.
                %apareceEnDoc = undef;}
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


En total son 150 líneas de código; no sé qué tan bueno será ponerlo todo.

Muchas Gracias nuevamente y gracias por la bienvenida.

Espero me puedan ayudar con esto también.
RWing
Perlero nuevo
Perlero nuevo
 
Mensajes: 3
Registrado: 2009-06-12 18:36 @817

Notapor explorer » 2009-06-13 17:43 @780

No tienes que hacer un undef() del diccionario, sino que en cada vuelta en que necesites usar un nuevo diccionario fresco, decirlo así:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
my %apareceEnDoc;
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

Esto lo pones dentro de sub archivo(), justo antes del primer foreach() (es decir, al mismo nivel de contexto que el push() final).

El objetivo es el siguiente: cuando la subrutina archivo() sea llamada, se crea un diccionario %apareceEnDoc nuevo, que se almacenará en @paraPostings. Al terminar la subrutina, como es una variable local definida con el operador my(), debería desaparecer, pero no lo hace, porque está siendo referenciada por el arreglo. A la hora de llamar de nuevo a la subrutina, el proceso se repite: crea un nuevo diccionario, se usa y se guarda su referencia. Y este segundo diccionario, aunque se llama igual que el anterior, no tienen nada que ver entre sí: los hemos declarado como locales a la función, por lo que son nuevos en cada ejecución de la subrutina.

Esta es la manera que tiene Perl de crear estructuras de datos, algo que en otros lenguajes, como C y C++, lo haríamos con el operador new().

Recuerda: una variable no termina de desaparecer hasta que se eliminan todas las referencias a ella.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14486
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Agradecimiento

Notapor RWing » 2009-06-13 20:14 @884

Realmente les quiero agradecer por la ayuda brindada.

Después de una lectura exhaustiva me di cuenta que podía hacer algo con la declaración de variable locales y no globales, sin embargo no entendía muy bien como hacerlo.

Ahí traveseando y haciendo pruebas obtuve una solución que me parece que es muy parecida a lo que me aconsejaron, pero un poco más ineficiente.

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
               
               #creo una variable local y le asigno el hash para crear una copia
               local %aparece = %apareceEnDoc;
                #agrega el hash con los terminos y sus fercuencias a un arreglo para la obtener el posting mas adelante (inserto la copia con direcion local)
                push(@paraPostings, \%aparece);
               #Pongo en blanco el hash global
                undef %apareceEnDoc;
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


Sin embargo, lo probé como me dijo y funciona excelente.

Realmente muchas gracias.

---
Ricardo Wing Alcázar
ClearCore
www.clearcore.co.cr
RWing
Perlero nuevo
Perlero nuevo
 
Mensajes: 3
Registrado: 2009-06-12 18:36 @817


Volver a Intermedio

¿Quién está conectado?

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

cron