Aprendendo o tipo de dado HASH {=>}

Foto de Anderson

Vamos desvendar o conceito de Hash! Mas antes, é essencial entender o que é um array. Um array é composto de elementos, um hash também.

O que muda entre um array e um hash é basicamente o endereço (key) do elemento: com Array é um número enquanto que com hash é uma palavra (string). Portanto, hash é um array com chaves não-numéricas.

Essa palavra é chamada de key string ou palavra-chave ou simplesmente key, chave, que é o "endereço" do elemento.

Portanto, você precisa definir a chave e o valor associado a ela. Desta feita, o Hash é similar à um array de duas colunas onde a chave é definida na esquerda e o valor na direita.

Em um hash você precisa saber a chave para obter o valor. Em um array você precisa saber a posição numérica para obter o valor.

Como criar um hash vazio

hPESSOA := {=>} 

ou

hPESSOA := HASH()

EXEMPLO COM UM HASH SIMPLES

Tudo vai ficar mais claro com um exemplo! Vamos definir uma hash hPESSOA que contém 3 tipos de dados: caracter, numérico e data. Vejamos:

FUNCTION MAIN()
SET DATE BRITISH
hPESSOA := {"NOME" => "JOSÉ MANUEL", "IDADE" => 35, "DNASC" => CTOD("25/11/87")}
// Para obter os dados desse hash e testar os tipos de dados faríamos assim:
? hPESSOA["NOME"],          VALTYPE(hPESSOA["NOME"])
? hPESSOA["IDADE"],         VALTYPE(hPESSOA["IDADE"])
? hPESSOA["DNASC"],         VALTYPE(hPESSOA["DNASC"])

Resultado:

hash

 

EXEMPLO DE HASH MULTIDIMENSIONAL

Eis um exemplo de hash com tamanho fixo e dimensões diferentes:

FUNCTION ATUCTR(cCTR)
// FUNÇÃO P/ OBTER OS DADOS ATUALIZADOS DO CONTRATO
hATUCTR := {"VALOR" => {"INICIAL" => EMP->CONTRATADO, "ATUAL" => 0},;
			"VIGENCIA" => {"INICIAL" => EMP->VIGEINI, "FINAL" => EMP->VIGEFIM, "ATUAL" => CTOD("")};
			}
// [...] ROTINA PARA BUSCAR O VALOR ATUAL DO CONTRATO, SE HOUVER
hATUCTR["VALOR"]["ATUAL"] := TA->ATUALIZADO
// [...] ROTINA PARA BUSCAR A PRORROGAÇÃO DO CONTRATO, SE HOUVER
hATUCTR["VIGENCIA"]["ATUAL"] := TA->PRAZO

//  CASO AINDA NÃO HAJA REAJUSTE OU PRORROGAÇÃO, TAIS HASHes SERÃO VAZIOS
RETURN hATUCTR // RETORNA HASH C/ DADOS

 

EXEMPLO DE HASH MULTIDIMENSIONAL DA VIDA REAL

Um hash não vai aparecer tão fácil na vida real como no exemplo básico anterior. Vamos complicar um pouquinho mais agora para ficar mais realista a coisa.

O hash é usado em páginas web, web-services e estão em muitas outras linguagens de programação e costumam trazer um registro do banco de dados.

No exemplo abaixo, o X normalmente é o ID, é o número do registro, tipo um RECNO(). Vejamos então como seria esse exemplo de hash para gravar e ler dados de 3 pessoas:

FUNCTION MAIN()
SET DATE BRITISH
hGRUPO := { "PESSOA" => {{"NOME" => "JOSÉ MANUEL ", "IDADE"=>35, "DNASC"=>CTOD("25/11/87")}, ;
						 {"NOME" => "JOSÉ MAMÃO  ", "IDADE"=>38, "DNASC"=>CTOD("25/11/84")}, ;
						 {"NOME" => "JOSÉ PEREIRA", "IDADE"=>32, "DNASC"=>CTOD("25/11/90")}  ;
                        } ;
          } 
             
? LEN(hGRUPO["PESSOA"])
FOR X=1 TO LEN(hGRUPO["PESSOA"])
    ? hGRUPO["PESSOA"][X]["NOME"], hGRUPO["PESSOA"][X]["IDADE"], hGRUPO["PESSOA"][X]["DNASC"]
NEXT   

Resultado:

Hash Multidimensional

 

Diferença entre KEY e INDEX

Key é o hash. Index é o índice do elemento do hash.

Em um hash multidimensional (nested hash) a função HHASKEY() é muito relevante porque antes de tentar acessar um elemento desse hash primeiro é preciso saber se ele está presente nele senão dará erro de acesso ao array (isso mesmo, array).

Digamos que você leu um arquivo de texto com seções e campos, você pode transformar as seções num hash multidimensional ou hash aninhado (nested hash), cada seção é um hash dentro do hash. Cada campo da seção se torna um elemento desse hash. Todavia, pode ser que nem sempre apareça as mesmas seções no texto então você terá que testar sua presença com HHASKEY() antes de tentar acessar, pois se tentar acessar algo que não exista dará erro. Fiz algo assim com os retornos do ACBR, caiu como uma luva.

 

JSON para HASH, da web para [x]Harbour!

Esta função transforma uma variável hash da web conhecida como JSON em uma variável hash usada no [x]Harbour feita nele próprio sem necessidade de linkar nenhuma LIB.

Observe que ele usa a função StrTran() usada para substituir uma string por outra, traduzindo a sintaxe (convertendo o formato) do JSON para o HASH do [x]Harbour. Vejamos:

Function JSontoHash( cStringJson )
/***
* Converte string formato Json em Hash
*/
Local hJson := {=>}
cStringJson := StrTran( cStringJson,':[','=>{')
cStringJson := StrTran( cStringJson,'":"','" => "')
cStringJson := StrTran( cStringJson,'[','{')
cStringJson := StrTran( cStringJson,']','}')
cStringJson := StrTran( cStringJson,'":null','"=>nil')
cStringJson := StrTran( cStringJson,'":true' ,'"=>.t.' )
cStringJson := StrTran( cStringJson,'":false','"=>.f.')
cStringJson := StrTran( cStringJson,'":','"=>')
cStringJson := StrTran( cStringJson,"\/","/" )
hJSon := &( cStringJson )
Return hJson

Tecnicamente a função acima deve funcionar 100% das vezes, mas caso contrário tente utilizar a lib correspondente da função HB_JSONDECODE().

 

A FUNÇÃO NATIVA HB_JSONDECODE()

Harbour 3.2 e xHarbour 1.2.3 terão já prontas na instalação nativa a função acima para resolver os problemas.

	// RESOLVE ACENTUAÇÃO GRÁFICA DA LINGUA PORTUGUESA
	#ifndef __XHARBOUR	
		JSONCNPJ := Win_OemToAnsi(http:responseText)
	#else
		JSONCNPJ := HB_AnsiToOem(http:responseText)
	#endif
	// CONVERTE JSON PARA HASH
	hb_jsonDecode( JSONCNPJ, @hCNPJA )

No exemplo, pegamos a string do webservice na variável JSONCNPJ e convertemos ela em hash atribuindo à variável hCNPJA.

Total votes: 0

Comentários

Qual sentido?

Foto de Anderson

Comment: 

A chave deve ser uma coisa fácil de lembrar e associar à informação à que está atribuída. Não vejo sentido colocar um número ou data, mas se pode e precisa de alguma forma que não consigo imaginar qual... tudo bem. Vai da experiência de cada um.

Usando xHarbour v1.2.3 Rev. 10264 + BCC 5.8, DBFCDX e SIBRA para imprimir relatórios.

Páginas