Página 1 de 3

Ordenar (SORT) uma Hash Table

Enviado: 02 Dez 2017 18:13
por asimoes
Pessoal,

Alguém saberia informar como fazer um sort em uma hash table

Ex.:

Código: Selecionar todos

   DbUseArea(.T.,"DBFCDX", "CADASTRO", "CADASTRO", .T.)
   nFields  := CADASTRO->( FCount() )
   hRecords := { => }
   DO WHILE ! CADASTRO->( Eof() )
      hRecord := { => }
      FOR nField := 1 TO nFields
         hb_HSet( hRecord, FieldName( nField ), FieldGet( nField ) ) // for each record, hrecord holds a hash of column name: column value
      NEXT
      hb_HSet( hRecords, hb_NtoS( RecNo() ), hRecord ) // like so, a hash of recno: hash of columns/values of this record 
      CADASTRO->( DbSkip() )
   ENDDO
Imaginando que eu queira ordenar pelo campo NOME que está na tabela cadastro ou pelo campo CODIGO após popular a hash table ?

Ordenar (SORT) uma Hash Table

Enviado: 02 Dez 2017 20:48
por asimoes
Não é o que eu queria mas já vai ajudar
Usei aSort para ordenar por CODIGO ou NOME

Código: Selecionar todos

   aOrdemN := { 1, 5, 3, 2, 4 }
   aOrdemC := { "Y", "A", "X", "D", "B" }
   aLines  := Array(5, 2) // 5 elementos com 2 dimensões
   FOR I:=1 TO Len( aLines )
      aLines[i,1] := { "CODIGO" => hb_NtoS(  aOrdemN[I]) }
      aLines[i,2] := { "NOME" => aOrdemC[I] }
   NEXT
   
   aSort( aLines ,,, {|x,y| y[2]["NOME"] > x[2]["NOME"]} )
   
   FOR EACH oElemento IN aLines
      hwg_MsgInfo( oElemento[2]["NOME"] )
   NEXT

Ordenar (SORT) uma Hash Table

Enviado: 03 Dez 2017 11:33
por JoséQuintas
Não sei se é isto:
hbmk2 -find sort

Harbour core (installed):
ASort()
hb_HSort()

Ordenar (SORT) uma Hash Table

Enviado: 03 Dez 2017 11:59
por asimoes
Tentei hb_HSort, mas não funcionou, não encontrei nenhum exemplo para o que eu preciso.

Ordenar (SORT) uma Hash Table

Enviado: 03 Dez 2017 12:10
por JoséQuintas
A impressão que tenho é que isso é um array de hash, e não um hash

Ordenar (SORT) uma Hash Table

Enviado: 03 Dez 2017 12:14
por JoséQuintas

Código: Selecionar todos

#define ELE_CODIGO 1
#define ELE_NOME     2

   aOrdemN := { 1, 5, 3, 2, 4 }
   aOrdemC := { "Y", "A", "X", "D", "B" }
   aLines  := Array( 5 )
   FOR I:=1 TO Len( aLines )
     aLines[ nCont ] :=  { hb_NtoS(  aOrdemN[I]), aOrdemC[I] } }
   NEXT
   
   aSort( aLines ,,, {|x,y| y[ ELE_NOME ] > x[ ELE_NOME ] } )
   
   FOR EACH oElemento IN aLines
      hwg_MsgInfo( oElemento[ ELE_NOME ] )
   NEXT

Ordenar (SORT) uma Hash Table

Enviado: 03 Dez 2017 13:39
por asimoes
Quintas,

Você resolveu essa parte, no seu exemplo pra funcionar:

Código: Selecionar todos

aLines[i]    := { "CODIGO" => hb_NtoS(  aOrdemN[I]), "NOME" => aOrdemC[I] } 
E

Código: Selecionar todos

aSort( aLines ,,, {|x,y| y[ "CODIGO" ] > x[ "CODIGO" ] } )
   
FOR EACH oElemento IN aLines
   ? oElemento["CODIGO"], oElemento["NOME"]
NEXT

Ordenar (SORT) uma Hash Table

Enviado: 03 Dez 2017 14:05
por asimoes
Usando aAdd

Código: Selecionar todos

aAdd( aLines, { "CODIGO" => hb_NtoS(  aOrdemN[I] ), "NOME" => aOrdemC[I]  } )

Ordenar (SORT) uma Hash Table

Enviado: 03 Dez 2017 14:14
por asimoes
O legal da hash table é que você só precisa saber o nome do elemento além de ficar mais "entendível" rs

Ordenar (SORT) uma Hash Table

Enviado: 03 Dez 2017 16:05
por JoséQuintas
Prefiro do outro jeito:

Código: Selecionar todos

FOR EACH oElemento IN aLines
   ? oElemento["CODIGO"], oElemento["NOME"]
NEXT

Código: Selecionar todos

FOR EACH oElemento IN aLines
   ? oElemento[ ELE_CODIGO ], oElemento[ ELE_NOME ]
NEXT
Diferença:
No primeiro é string, não dá pra saber se digitou errado, vai dar erro na execução.
No segundo é #define, se digitar errado, já dá erro na própria compilação.
E o fonte tá bem parecido.

Ordenar (SORT) uma Hash Table

Enviado: 03 Dez 2017 16:10
por JoséQuintas
Aproveitando.....
Rolou um aparente bug do Harbour com Hash no grupo Harbour-users.
No reaproveitamento de variável hash, melhor atribuir NIL à variável e não apenas {}.
Pelo menos enquanto isso não for resolvido.

Ordenar (SORT) uma Hash Table

Enviado: 03 Dez 2017 19:11
por asimoes
Se for criar uma tabela temporária com hash usando os nomes dos campos a partir do dbf não poderá ser por #define, enfim, se tem erro é culpa do programador, kkkk, se vira pra consertar.

Ordenar (SORT) uma Hash Table

Enviado: 04 Dez 2017 10:24
por asimoes
Seguindo com os testes...

Código: Selecionar todos

   DbUseArea(.T., "DBFCDX", "CADASTRO", "CADASTRO", .T.)
   nFields    := CADASTRO->( FCount() )
   aRegistros := {}
   DO WHILE ! CADASTRO->( Eof() )
      hRecord := { => }
      FOR nField := 1 TO nFields
         hb_HSet( hRecord, FieldName( nField ), FieldGet( nField ) ) // for each record, hrecord holds a hash of column name: column value
      NEXT
      aAdd( aRegistros, hRecord )
      CADASTRO->( DbSkip() )
   ENDDO
   FOR EACH oElemento IN aRegistros
      ? oElemento["CODIGO"], oElemento["NOME"]
   NEXT

Ordenar (SORT) uma Hash Table

Enviado: 23 Out 2018 21:23
por asimoes
Voltando ao assunto:

O DBF tem 2 campos, CODIGO E NOME
aSort funciona, Hb_HSort não.

Código: Selecionar todos

   hTable := Hb_Hash()
   aRegistros := {}
   DO WHILE ! CADASTRO->( Eof())
      hRecord := {=>}
      FOR nField := 1 TO nFields
         Hb_HSet( hRecord, FieldName( nField ), FieldGet( nField ) ) // for each record, hrecord holds a hash of column name: column value
      NEXT
      aAdd( aRegistros, hRecord )
      CADASTRO->( DbSkip() )
   ENDDO
   
* Ordenando por CODIGO       
   aSort( aRegistros ,,, {|x,y,z| y[ "CODIGO" ] > x[ "CODIGO" ] } )
   FOR EACH oElemento IN aRegistros
      ? oElemento["CODIGO"] + " " + oElemento["NOME"]
   NEXT

   ?

* Ordenando por NOME   
   aSort( aRegistros ,,, {|x,y| y[ "NOME" ] > x[ "NOME" ] } )
   FOR EACH oElemento IN aRegistros
      ? oElemento["CODIGO"] + " " + oElemento["NOME"]
   NEXT



Ordenar (SORT) uma Hash Table

Enviado: 23 Out 2018 22:28
por JoséQuintas
É isso que dá não ler meus posts kkkkk
A solução já está nos posts anteriores.