Basicamente, estou tentando criar um objeto de objetos únicos, um conjunto. Eu tive a brilhante idéia de apenas usar um objeto JavaScript com objetos para os nomes das propriedades. Tal como,
set[obj] = true;
Isso funciona, até certo ponto. Funciona muito bem com string e números, mas com outros objetos, todos parecem "hash" com o mesmo valor e acessam a mesma propriedade. Existe alguma maneira de gerar um valor de hash exclusivo para um objeto? Como seqüências de caracteres e números fazem isso, posso substituir o mesmo comportamento?
javascript
hash
set
hashcode
Boog
fonte
fonte
JSON.stringify(obj)
ouobj.toSource()
pode funcionar para você, dependendo do problema e da plataforma de destino.toSource
não funcionam no Chrome btwRespostas:
Os objetos JavaScript podem usar apenas cadeias de caracteres como chaves (qualquer outra coisa é convertida em uma cadeia de caracteres).
Como alternativa, você pode manter uma matriz que indexa os objetos em questão e usar sua string de índice como uma referência ao objeto. Algo assim:
Obviamente, é um pouco detalhado, mas você pode escrever alguns métodos que lidam com isso e obter e definir tudo de maneira desagradável.
Editar:
Isso traz outro ponto interessante; você pode definir um método toString nos objetos que deseja hash e que podem formar seu identificador de hash.
fonte
Se você deseja uma função hashCode () como Java em JavaScript, essa é sua:
Essa é a maneira de implementação em Java (operador bit a bit).
Observe que o hashCode pode ser positivo e negativo, e isso é normal, consulte HashCode fornecendo valores negativos . Portanto, você pode considerar usar
Math.abs()
junto com esta função.fonte
char
é uma palavra reservada em JS e pode causar alguns problemas. Algum outro nome seria melhor.pickOne["helloo".hashCode() % 20]
uma matrizpickOne
com 20 elementos. Eu recebiundefined
porque o código de hash é negativo, então este é um exemplo em que alguém (eu) assumiu implicitamente códigos de hash positivos.A maneira mais fácil de fazer isso é atribuir a cada um de seus objetos seu próprio
toString
método exclusivo :Eu tive o mesmo problema e isso resolveu-o perfeitamente para mim com o mínimo de confusão e foi muito mais fácil reimplementar algum estilo Java gordo
Hashtable
e adicionarequals()
e adicionarhashCode()
às suas classes de objetos. Apenas certifique-se de não colocar uma string '<#MyObject: 12> no seu hash ou isso limpará a entrada do seu objeto existente com esse ID.Agora todos os meus hashes estão totalmente relaxados. Também acabei de publicar uma entrada de blog há alguns dias sobre esse tópico exato .
fonte
equals()
e,hashCode()
portanto, dois objetos equivalentes têm o mesmo valor de hash. O uso do método acima significa que cada instância deMyObject
terá uma cadeia única, o que significa que você precisará manter uma referência a esse objeto para recuperar o valor correto do mapa. Ter uma chave não tem sentido, porque não tem nada a ver com a singularidade de um objeto. UmatoString()
função útil precisará ser implementada para o tipo específico de objeto que você está usando como chave.toString
para os objetos de forma que ele mapeie diretamente para uma relação de equivalência, para que dois objetos criem a mesma string se forem considerados "iguais".toString()
para permitir que você use umObject
como aSet
. Acho que não entendi sua resposta como uma tentativa de fornecer uma solução genérica para evitar escrever umtoString()
equivalenteequals()
ouhashCode()
caso a caso.O que você descreveu é coberto pelo Harmony WeakMaps , parte da especificação do ECMAScript 6 (próxima versão do JavaScript). Ou seja: um conjunto em que as chaves podem ser qualquer coisa (incluindo indefinidas) e não enumeráveis.
Isso significa que é impossível obter uma referência a um valor, a menos que você tenha uma referência direta à chave (qualquer objeto!) Vinculada a ele. É importante por várias razões de implementação de mecanismo relacionadas à eficiência e à coleta de lixo, mas também é super legal, pois permite novas semânticas, como permissões de acesso revogáveis e passagem de dados sem expor o remetente.
Do MDN :
Os WeakMaps estão disponíveis no Firefox, Chrome e Edge atuais. Eles também são suportados no nó v7 e na v6 com o
--harmony-weak-maps
sinalizador.fonte
Map
?var m = new Map();m.set({},"abc"); console.log(m.get({}) //=>undefined
Só funciona se você tiver a mesma variável que você referenciou originalmente no comando set. EGvar m = new Map();a={};m.set(a,"abc"); console.log(m.get(a) //=>undefined
A solução que escolhi é semelhante à de Daniel, mas, em vez de usar uma fábrica de objetos e substituir o toString, adiciono explicitamente o hash ao objeto quando ele é solicitado pela primeira vez por meio da função getHashCode. Um pouco bagunçado, mas melhor para as minhas necessidades :)
fonte
Object.defineProperty
comenumerable
set comofalse
, para que você não troque nenhumfor .. in
loop.Para minha situação específica, só me preocupo com a igualdade do objeto, tanto quanto as chaves e os valores primitivos. A solução que funcionou para mim foi converter o objeto em sua representação JSON e usá-lo como hash. Existem limitações como ordem de definição de chave potencialmente inconsistente; mas como eu disse, funcionou para mim porque todos esses objetos estavam sendo gerados em um só lugar.
fonte
Eu montei um pequeno módulo JavaScript há algum tempo para produzir códigos de hash para strings, objetos, matrizes, etc. (acabei de o comprometer com o GitHub :))
Uso:
fonte
var hash1 = Hashcode.value({ a: 1, b: 2 }); var hash2 = Hashcode.value({ a: 2, b: 1 }); console.log(hash1, hash2);
irá registrar2867874173
2867874173
A especificação JavaScript define o acesso à propriedade indexada como executando uma conversão toString no nome do índice. Por exemplo,
é o mesmo que
Isso é necessário, como no JavaScript
é o mesmo que
E sim, isso também me deixa triste :-(
fonte
No ECMAScript 6, agora existe um
Set
que funciona como você deseja: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SetJá está disponível no Chrome, FF e IE11 mais recentes.
fonte
Referência: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol
você pode usar o símbolo Es6 para criar chave exclusiva e objeto de acesso. Todo valor de símbolo retornado de Symbol () é exclusivo. Um valor de símbolo pode ser usado como um identificador para propriedades do objeto; esse é o único objetivo do tipo de dados.
fonte
Aqui está minha solução simples que retorna um número inteiro exclusivo.
fonte
hashcode({a:1, b:2}) === hashcode({a:2, b:1})
e muitos outros conflitos.Com base no título, podemos gerar hashes fortes com js, ele pode ser usado para gerar um hash exclusivo de um objeto, uma matriz de parâmetros, uma string ou qualquer outra coisa.
Posteriormente, para indexar isso, evite possíveis erros de correspondência, enquanto permite recuperar um índice dos parâmetros (evite pesquisar / fazer um loop no objeto, etc.):
A saída acima no meu navegador também deve ser igual para você ( é mesmo? ):
https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/digest#Converting_a_digest_to_a_hex_string
fonte
Minha solução introduz uma função estática para o
Object
objeto global .Eu acho que isso é mais conveniente com outras funções de manipulação de objetos em JavaScript.
fonte
Vou tentar ir um pouco mais fundo do que outras respostas.
Mesmo se o JS tivesse um suporte melhor ao hash, ele não usaria magicamente tudo perfeitamente, em muitos casos, você terá que definir sua própria função de hash. Por exemplo, Java possui um bom suporte de hash, mas você ainda precisa pensar e fazer algum trabalho.
Um problema é com o termo hash / hashcode ... há hash criptográfico e hash não criptográfico. O outro problema é que você precisa entender por que o hash é útil e como ele funciona.
Quando falamos sobre hash em JavaScript ou Java, na maioria das vezes, falamos sobre hash não criptográfico, geralmente sobre hash para hashmap / hashtable (a menos que trabalhemos em autenticação ou senhas, o que você poderia fazer no servidor usando o NodeJS. ..)
Depende dos dados que você possui e do que deseja alcançar.
Seus dados têm alguma singularidade "simples" natural:
Seus dados têm alguma exclusividade "composta" natural:
Você não tem idéia de quais serão seus dados:
Não existe uma técnica de hash magicamente eficiente para dados desconhecidos; em alguns casos, é bastante fácil; em outros casos, pode ser necessário pensar duas vezes. Portanto, mesmo que o JavaScript / ECMAScript inclua mais suporte, não há solução de linguagem mágica para esse problema.
Na prática, você precisa de duas coisas: singularidade suficiente, velocidade suficiente
Além disso, é ótimo ter: "código de hash igual se os objetos forem iguais"
fonte
Se você realmente deseja definir um comportamento (estou familiarizado com o conhecimento de Java), será difícil encontrar uma solução em JavaScript. A maioria dos desenvolvedores recomendará uma chave exclusiva para representar cada objeto, mas isso é diferente do definido, pois você pode obter dois objetos idênticos, cada um com uma chave exclusiva. A API Java realiza o trabalho de verificação de valores duplicados comparando valores de código de hash, não chaves, e como não há representação de valor de código de hash de objetos em JavaScript, torna-se quase impossível fazer o mesmo. Até a biblioteca Prototype JS admite essa falha, quando diz:
http://www.prototypejs.org/api/hash
fonte
Além da resposta da ausência de pálpebra, aqui está uma função que retorna um ID exclusivo e reproduzível para qualquer objeto:
Como você pode ver, ele usa uma lista de pesquisa que é muito ineficiente, mas é o melhor que pude encontrar por enquanto.
fonte
Se você quiser usar objetos como chaves, precisará substituir o método toString, como alguns já mencionados aqui. As funções de hash usadas são boas, mas funcionam apenas para os mesmos objetos e não para objetos iguais.
Eu escrevi uma pequena biblioteca que cria hashes a partir de objetos, que você pode usar facilmente para esse fim. Os objetos podem até ter uma ordem diferente, os hashes serão os mesmos. Internamente, você pode usar tipos diferentes para seu hash (djb2, md5, sha1, sha256, sha512, ripemd160).
Aqui está um pequeno exemplo da documentação:
O pacote pode ser usado no navegador e nos Nó-Js.
Repositório: https://bitbucket.org/tehrengruber/es-js-hash
fonte
Se você deseja ter valores exclusivos em um objeto de pesquisa, pode fazer algo assim:
Criando um objeto de pesquisa
Configurando a função hashcode
Objeto
Matriz
Outros tipos
Resultado final
{ 1337: true, 01132337: true, StackOverflow: true }
Observe que
getHashCode
não retorna nenhum valor quando o objeto ou a matriz está vaziaIsso é semelhante à solução @ijmacd, apenas
getHashCode
não temJSON
dependência.fonte
Combinei as respostas de eyelidlessness e KimKha.
A seguir, é um serviço angularjs e suporta números, seqüências de caracteres e objetos.
Exemplo de uso:
Resultado
Explicação
Como você pode ver, o coração do serviço é a função hash criada por KimKha. Adicionei tipos às seqüências de caracteres para que a estrutura do objeto também impactasse o valor final do hash. As chaves são hash para evitar colisões de objetos |
A comparação de objetos sem pálpebras é usada para evitar recursões infinitas por objetos auto-referenciados.
Uso
Eu criei este serviço para poder ter um serviço de erro que é acessado com objetos. Para que um serviço possa registrar um erro em um determinado objeto e outro possa determinar se foram encontrados erros.
ie
JsonValidation.js
UserOfData.js
Isso retornaria:
Enquanto
Isso retornaria
fonte
Basta usar a propriedade secreta oculta com o
defineProperty
enumerable: false
Funciona muito rápido :
fonte