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:
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:
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.
Comentários
Aprendendo o tipo de dado HASH {=>}
Comment:
Olá!
Ao contrário do que diz o post, a chave de um hash não precisa ser obrigatoriamente do tipo carácter. Pode ser númerica, date...
Qual sentido?
Comment:
Usando xHarbour v1.2.3 Rev. 10264 + BCC 5.8, DBFCDX e SIBRA para imprimir relatórios.
Páginas