HASH con uno de los key que es un array

Post Reply
Verhoven
Posts: 565
Joined: Sun Oct 09, 2005 7:23 pm

HASH con uno de los key que es un array

Post by Verhoven »

Buenas tardes,
Me estoy encontrando con un problema que no entiendo con un hash.
Mi problema consiste en que el único valor del hash que no es correcto es el que es un array. Porque cuando acaba el bucle siempre muestra los valores de la última asignación que le hecho dentro del mismo. Es como si tomara la referencia a la posición de memoria del array que se le asigna en vez de los valores que contiene.

En un bucle hago algo como lo siguiente:
aSalida:={}
aIntervenciones:={} //array
hDatos:={=>} //hash

do while
hDatos["nombre"]=DBF->NOMBRE
hDatos["calle"]=DBF->CALLE
hDatos["intervenciones"]={} //Resetea las intervenciones para el nuevo nombre
while DBF->NOMBRE == hDatos["nombre"
aadd(aIntervenciones, DBF->NUMINTERV)
DBF->(dbskip(+1))
enddo
//Graba los datos
aadd(aSalida, hDatos)
enddo

xbrowse(aSalida) // Muestra distintos todos los valores del hash como hDatos["nombre"] y hDatos["calle"], pero el valor de hDatos["intervenciones"] es el mismo para todos e igual al del último registro que se procesó en el bucle.

User avatar
Antonio Linares
Site Admin
Posts: 44515
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain
Contact:

Re: HASH con uno de los key que es un array

Post by Antonio Linares »

El objetivo del código parece ser procesar un archivo de base de datos (DBF) para agrupar las intervenciones por nombre y almacenarlas en un array de salida.

Aquí tienes la corrección y explicación.

🛠️ Código Corregido

Suponiendo que el bucle exterior es el que itera a través de todos los registros del archivo DBF (algo que el fragmento original omite), esta es la estructura correcta del bucle DO WHILE/ENDDO:

Code: Select all | Expand

// Bucle exterior: Itera a través de todos los registros del DBF
DO WHILE !Eof()

    // 1. Inicializar el hash de datos para el nombre actual
    hDatos := {} // Inicializa un nuevo hash para el registro actual
    hDatos["nombre"] := DBF->NOMBRE
    hDatos["calle"] := DBF->CALLE
    hDatos["intervenciones"] := {} // Array para almacenar las intervenciones

    // 2. Bucle interior: Recorre todos los registros que tengan el mismo nombre
    // Se usa un DO WHILE o un WHILE más simple, ya que el primer registro ya es el nombre correcto
    WHILE !Eof() .AND. DBF->NOMBRE == hDatos["nombre"]
        
        // Agregar el número de intervención al array del hash
        AADD(hDatos["intervenciones"], DBF->NUMINTERV)
        
        // Mover al siguiente registro
        DBF->(DBSKIP(+1))
    
    ENDDO // Fin del WHILE interior (mismo nombre)

    // 3. Grabar los datos agrupados
    AADD(aSalida, hDatos)

ENDDO // Fin del DO WHILE exterior (fin de archivo)
🔍 Errores y Explicación

Los principales errores en tu código original eran:

  1. Sintaxis Incompleta en el WHILE:

    • Original: while DBF->NOMBRE == hDatos["nombre"
      • Corrección: Faltaba el paréntesis de cierre, y lo más importante, se necesitaba la condición !Eof() (mientras no sea el fin del archivo) para evitar un error cuando se llega al final.
      • Corregido: WHILE !Eof() .AND. DBF->NOMBRE == hDatos["nombre"]
  2. Uso Incorrecto del DO WHILE:

    • Original: El código usaba enddo sin un do while previo para el bucle interior. En el código xBase, un bucle WHILE se cierra con ENDDO o ENDIF (dependiendo de la versión o dialecto), pero la estructura DO WHILE ... ENDDO tiene una semántica específica que implica un bucle. En el código corregido, se usa el WHILE ... ENDDO estándar para el bucle de agrupamiento.

  3. Variable aIntervenciones no Definida:

    • Original: aadd(aIntervenciones, DBF->NUMINTERV)

      • Corrección: El array de intervenciones estaba siendo reseteado en el hash (hDatos["intervenciones"]={}) pero se intentaba añadir el dato a una variable diferente (aIntervenciones). El dato debe añadirse al array que está dentro del hash: AADD(hDatos["intervenciones"], DBF->NUMINTERV).
  4. Inicialización de hDatos:

    • Para cada nuevo grupo de nombres, debes inicializar un nuevo hash. La línea hDatos := {} (que faltaba) asegura que no se sobrescriban los datos del registro anterior.

regards, saludos

Antonio Linares
www.fivetechsoft.com
Verhoven
Posts: 565
Joined: Sun Oct 09, 2005 7:23 pm

Re: HASH con uno de los key que es un array

Post by Verhoven »

Gracias Antonio.

Al final lo que lo ha arreglado era hacer un hb_clone(hashAcopiar)

Post Reply