En gros, j'essaye de créer un objet d'objets uniques, un ensemble. J'ai eu la brillante idée d'utiliser simplement un objet JavaScript avec des objets pour les noms de propriétés. Tel que,
set[obj] = true;
Cela fonctionne, jusqu'à un certain point. Cela fonctionne très bien avec des chaînes et des nombres, mais avec d'autres objets, ils semblent tous "hacher" à la même valeur et accéder à la même propriété. Existe-t-il un moyen de générer une valeur de hachage unique pour un objet? Comment les chaînes et les nombres le font, puis-je remplacer le même comportement?
javascript
hash
set
hashcode
Boog
la source
la source
JSON.stringify(obj)
ouobj.toSource()
peut fonctionner pour vous en fonction du problème et de la plate-forme cible.toSource
ne fonctionne pas dans Chrome btwRéponses:
Les objets JavaScript ne peuvent utiliser que des chaînes comme clés (tout le reste est converti en chaîne).
Vous pouvez également conserver un tableau qui indexe les objets en question et utiliser sa chaîne d'index comme référence à l'objet. Quelque chose comme ça:
De toute évidence, c'est un peu verbeux, mais vous pouvez écrire quelques méthodes pour le gérer et obtenir et définir tout bon gré mal gré.
Éditer:
Cela soulève un autre point intéressant; vous pouvez définir une méthode toString sur les objets que vous souhaitez hacher, et qui peuvent former leur identifiant de hachage.
la source
Si vous voulez une fonction hashCode () comme celle de Java en JavaScript, c'est la vôtre:
C'est le mode d'implémentation en Java (opérateur bit à bit).
Veuillez noter que hashCode peut être positif et négatif, et c'est normal, voir HashCode donnant des valeurs négatives . Donc, vous pouvez envisager d'utiliser
Math.abs()
avec cette fonction.la source
char
est un mot réservé dans JS et peut causer des problèmes. Un autre nom serait mieux.pickOne["helloo".hashCode() % 20]
pour un tableaupickOne
avec 20 éléments. J'ai obtenuundefined
parce que le code de hachage est négatif, c'est donc un exemple dans lequel quelqu'un (moi) a implicitement supposé des codes de hachage positifs.Le moyen le plus simple de le faire est de donner à chacun de vos objets sa propre
toString
méthode unique :J'ai eu le même problème et cela l'a parfaitement résolu pour moi avec un minimum de tracas, et c'était beaucoup plus facile que de réimplémenter un style Java gras
Hashtable
et d'ajouterequals()
ethashCode()
à vos classes d'objets. Assurez-vous simplement que vous ne collez pas également une chaîne '<#MyObject: 12> dans votre hachage ou cela effacera l'entrée de votre objet existant avec cet identifiant.Maintenant, tous mes hashes sont totalement froids. Je viens également de publier une entrée de blog il y a quelques jours sur ce sujet précis .
la source
equals()
ethashCode()
pour que deux objets équivalents aient la même valeur de hachage. L'utilisation de la méthode ci-dessus signifie que chaque instance deMyObject
aura une chaîne unique, ce qui signifie que vous devrez conserver une référence à cet objet pour récupérer la valeur correcte de la carte. Avoir une clé n'a pas de sens, car cela n'a rien à voir avec l'unicité d'un objet. UnetoString()
fonction utile devra être implémentée pour le type spécifique d'objet que vous utilisez comme clé.toString
pour les objets de telle sorte qu'il mappe directement à une relation d'équivalence de sorte que deux objets créent la même chaîne ssils sont considérés comme "égaux".toString()
pour vous permettre d'utiliser unObject
fichierSet
. Je pense que j'ai mal compris votre réponse en essayant de fournir une solution générique pour éviter d'écrire untoString()
équivalentequals()
ouhashCode()
au cas par cas.Ce que vous avez décrit est couvert par Harmony WeakMaps , qui fait partie de la spécification ECMAScript 6 (prochaine version de JavaScript). C'est-à-dire: un ensemble où les clés peuvent être n'importe quoi (y compris indéfini) et ne sont pas énumérables.
Cela signifie qu'il est impossible d'obtenir une référence à une valeur à moins d'avoir une référence directe à la clé (n'importe quel objet!) Qui y est liée. C'est important pour un tas de raisons d'implémentation de moteur liées à l'efficacité et au ramassage des ordures, mais c'est aussi super cool car cela permet une nouvelle sémantique comme des autorisations d'accès révocables et la transmission de données sans exposer l'expéditeur de données.
De MDN :
WeakMaps est disponible dans Firefox, Chrome et Edge actuels. Ils sont également pris en charge dans Node v7 et dans v6 avec l'
--harmony-weak-maps
indicateur.la source
Map
?var m = new Map();m.set({},"abc"); console.log(m.get({}) //=>undefined
Cela ne fonctionne que si vous avez la même variable que vous avez initialement référencée dans la commande set. EGvar m = new Map();a={};m.set(a,"abc"); console.log(m.get(a) //=>undefined
La solution que j'ai choisie est similaire à celle de Daniel, mais plutôt que d'utiliser une fabrique d'objets et de remplacer le toString, j'ajoute explicitement le hachage à l'objet lorsqu'il est demandé pour la première fois via une fonction getHashCode. Un peu en désordre, mais mieux pour mes besoins :)
la source
Object.defineProperty
avecenumerable
set tofalse
, afin de ne planter aucunefor .. in
boucle.Pour ma situation spécifique, je ne me soucie que de l'égalité de l'objet en ce qui concerne les clés et les valeurs primitives. La solution qui a fonctionné pour moi a été de convertir l'objet en sa représentation JSON et de l'utiliser comme hachage. Il existe des limites telles que l'ordre de définition des clés pouvant être incohérent; mais comme je l'ai dit, cela a fonctionné pour moi parce que ces objets étaient tous générés au même endroit.
la source
J'ai mis en place un petit module JavaScript il y a quelque temps pour produire des hashcodes pour des chaînes, des objets, des tableaux, etc. (je viens de le valider dans GitHub :))
Usage:
la source
var hash1 = Hashcode.value({ a: 1, b: 2 }); var hash2 = Hashcode.value({ a: 2, b: 1 }); console.log(hash1, hash2);
se connecter2867874173
2867874173
La spécification JavaScript définit l'accès aux propriétés indexées comme effectuant une conversion toString sur le nom de l'index. Par exemple,
est le même que
C'est nécessaire comme en JavaScript
est le même que
Et oui, ça me rend triste aussi :-(
la source
Dans ECMAScript 6, il y a maintenant un
Set
qui fonctionne comme vous le souhaitez: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SetIl est déjà disponible dans les derniers Chrome, FF et IE11.
la source
Référence: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol
vous pouvez utiliser le symbole Es6 pour créer une clé unique et un objet d'accès. Chaque valeur de symbole renvoyée par Symbol () est unique. Une valeur de symbole peut être utilisée comme identificateur pour les propriétés d'objet; c'est le seul objectif du type de données.
la source
Voici ma solution simple qui renvoie un entier unique.
la source
hashcode({a:1, b:2}) === hashcode({a:2, b:1})
nombreux autres conflits.Sur la base du titre, nous pouvons générer des hachages forts avec js, il peut être utilisé pour générer un hachage unique à partir d'un objet, d'un tableau de paramètres, d'une chaîne ou autre.
Plus tard pour l'indexation, évitez toute erreur de correspondance possible, tout en permettant de récupérer un index à partir des paramètres (évitez de rechercher / boucler l'objet, etc.):
La sortie ci-dessus dans mon navigateur, elle devrait être égale pour vous aussi ( est-ce vraiment? ):
https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/digest#Converting_a_digest_to_a_hex_string
la source
Ma solution introduit une fonction statique pour l'
Object
objet global .Je pense que c'est plus pratique avec d'autres fonctions de manipulation d'objets en JavaScript.
la source
J'essaierai d'aller un peu plus loin que les autres réponses.
Même si JS avait un meilleur support de hachage, il ne hacherait pas tout parfaitement par magie, dans de nombreux cas, vous devrez définir votre propre fonction de hachage. Par exemple, Java a un bon support de hachage, mais vous devez encore réfléchir et faire un peu de travail.
Un problème est avec le terme hash / hashcode ... il y a un hachage cryptographique et un hachage non cryptographique. L'autre problème, c'est que vous devez comprendre pourquoi le hachage est utile et comment cela fonctionne.
Lorsque nous parlons de hachage en JavaScript ou Java la plupart du temps, nous parlons de hachage non cryptographique, généralement de hachage pour hashmap / hashtable (sauf si nous travaillons sur l'authentification ou les mots de passe, ce que vous pourriez faire côté serveur en utilisant NodeJS. ..).
Cela dépend des données dont vous disposez et de ce que vous souhaitez atteindre.
Vos données ont un caractère unique "simple" naturel:
Vos données ont un caractère unique "composite" naturel:
Vous n'avez aucune idée de ce que seront vos données:
Il n'y a pas de technique de hachage magiquement efficace pour les données inconnues, dans certains cas, c'est assez facile, dans d'autres cas, vous devrez peut-être réfléchir à deux fois. Donc, même si JavaScript / ECMAScript ajoute plus de support, il n'y a pas de solution de langage magique pour ce problème.
En pratique, vous avez besoin de deux choses: assez d'unicité, assez de vitesse
En plus de cela, il est génial d'avoir: "hashcode égal si les objets sont égaux"
la source
Si vous voulez vraiment définir un comportement (je me fie à Java), vous aurez du mal à trouver une solution en JavaScript. La plupart des développeurs recommanderont une clé unique pour représenter chaque objet, mais cela ne ressemble pas à un ensemble, en ce sens que vous pouvez obtenir deux objets identiques chacun avec une clé unique. L'API Java effectue le travail de vérification des valeurs en double en comparant les valeurs de code de hachage, pas les clés, et comme il n'y a pas de représentation de la valeur de code de hachage des objets en JavaScript, il devient presque impossible de faire de même. Même la bibliothèque Prototype JS admet cette lacune, quand elle dit:
http://www.prototypejs.org/api/hash
la source
En plus de la réponse sans paupière, voici une fonction qui renvoie un identifiant unique et reproductible pour tout objet:
Comme vous pouvez le voir, il utilise une liste de recherche qui est très inefficace, mais c'est le meilleur que je puisse trouver pour le moment.
la source
Si vous souhaitez utiliser des objets comme clés, vous devez écraser leur méthode toString, comme certains l'ont déjà mentionné ici. Les fonctions de hachage qui ont été utilisées sont toutes correctes, mais elles ne fonctionnent que pour les mêmes objets et non pour des objets égaux.
J'ai écrit une petite bibliothèque qui crée des hachages à partir d'objets, que vous pouvez facilement utiliser à cette fin. Les objets peuvent même avoir un ordre différent, les hachages seront les mêmes. En interne, vous pouvez utiliser différents types pour votre hachage (djb2, md5, sha1, sha256, sha512, ripemd160).
Voici un petit exemple de la documentation:
Le package peut être utilisé dans le navigateur et dans Node-Js.
Dépôt: https://bitbucket.org/tehrengruber/es-js-hash
la source
Si vous voulez avoir des valeurs uniques dans un objet de recherche, vous pouvez faire quelque chose comme ceci:
Création d'un objet de recherche
Configuration de la fonction de hashcode
Objet
Tableau
Autres types
Résultat final
{ 1337: true, 01132337: true, StackOverflow: true }
Notez que
getHashCode
ne renvoie aucune valeur lorsque l'objet ou le tableau est videCeci est similaire à la solution @ijmacd mais
getHashCode
n'a pas deJSON
dépendance.la source
J'ai combiné les réponses de la paupière et de KimKha.
Ce qui suit est un service angularjs et il prend en charge les nombres, les chaînes et les objets.
Exemple d'utilisation:
Production
Explication
Comme vous pouvez le voir, le cœur du service est la fonction de hachage créée par KimKha, j'ai ajouté des types aux chaînes afin que la structure de l'objet ait également un impact sur la valeur de hachage finale.Les clés sont hachées pour éviter les collisions tableau | objet.
La comparaison d'objets sans paupière est utilisée pour empêcher la récursivité infinie par les objets auto-référençables.
Usage
J'ai créé ce service pour pouvoir disposer d'un service d'erreur accessible avec des objets. Pour qu'un service puisse enregistrer une erreur avec un objet donné et qu'un autre puisse déterminer si des erreurs ont été trouvées.
c'est à dire
JsonValidation.js
UserOfData.js
Cela reviendrait:
Tandis que
Cela reviendrait
la source
Utilisez simplement la propriété secrète cachée avec le
defineProperty
enumerable: false
Cela fonctionne très vite :
la source