Básicamente, estoy tratando de crear un objeto de objetos únicos, un conjunto. Tuve la brillante idea de usar un objeto JavaScript con objetos para los nombres de propiedad. Como,
set[obj] = true;
Esto funciona, hasta cierto punto. Funciona muy bien con cadenas y números, pero con otros objetos, todos parecen "hash" al mismo valor y acceden a la misma propiedad. ¿Hay algún tipo de forma en que pueda generar un valor hash único para un objeto? ¿Cómo lo hacen las cadenas y los números? ¿Puedo anular el mismo comportamiento?
javascript
hash
set
hashcode
Boog
fuente
fuente
JSON.stringify(obj)
oobj.toSource()
puede funcionar para usted según el problema y la plataforma de destino.toSource
no trabajes en Chrome por ciertoRespuestas:
Los objetos de JavaScript solo pueden usar cadenas como claves (cualquier otra cosa se convierte en una cadena).
Alternativamente, podría mantener una matriz que indexe los objetos en cuestión y usar su cadena de índice como referencia al objeto. Algo como esto:
Obviamente es un poco detallado, pero podría escribir un par de métodos que lo manejen y obtengan y configuren todo lo contrario.
Editar:
Esto trae a colación otro punto interesante; puede definir un método toString en los objetos que desea hash, y eso puede formar su identificador hash.
fuente
Si desea una función hashCode () como Java en JavaScript, es suya:
Esa es la forma de implementación en Java (operador bit a bit).
Tenga en cuenta que hashCode podría ser positivo y negativo, y eso es normal, vea HashCode dando valores negativos . Por lo tanto, podría considerar usar
Math.abs()
junto con esta función.fuente
char
es una palabra reservada en JS y puede causar algunos problemas. Algún otro nombre sería mejor.pickOne["helloo".hashCode() % 20]
una matrizpickOne
con 20 elementos. Obtuveundefined
porque el código hash es negativo, por lo que este es un ejemplo en el que alguien (yo) asumió implícitamente códigos hash positivos.La forma más fácil de hacer esto es dar a cada uno de sus objetos su propio
toString
método único :Tuve el mismo problema y esto lo resolvió perfectamente para mí con un mínimo de alboroto, y fue mucho más fácil que volver a implementar algún estilo graso de Java
Hashtable
y agregarequals()
yhashCode()
a sus clases de objetos. Solo asegúrese de no pegar una cadena '<#MyObject: 12> en su hash o borrará la entrada de su objeto saliente con esa identificación.Ahora todos mis hash son totalmente fríos. También publiqué una entrada de blog hace unos días sobre este tema exacto .
fuente
equals()
yhashCode()
para que dos objetos equivalentes tengan el mismo valor hash. El uso del método anterior significa que cada instancia deMyObject
tendrá una cadena única, lo que significa que tendrá que mantener una referencia a ese objeto para recuperar el valor correcto del mapa. Tener una clave no tiene sentido, porque no tiene nada que ver con la singularidad de un objeto.toString()
Será necesario implementar una función útil para el tipo específico de objeto que está utilizando como clave.toString
para los objetos de modo que se asigne directamente a una relación de equivalencia para que dos objetos creen la misma cadena si se consideran "iguales".toString()
para permitirte usar unObject
como aSet
. Creo que entendí mal su respuesta al tratar de proporcionar una solución genérica para evitar escribir untoString()
equivalenteequals()
ohashCode()
caso por caso.Lo que describió está cubierto por Harmony WeakMaps , parte de la especificación ECMAScript 6 (próxima versión de JavaScript). Es decir: un conjunto donde las claves pueden ser cualquier cosa (incluso indefinidas) y no es enumerable.
Esto significa que es imposible obtener una referencia a un valor a menos que tenga una referencia directa a la clave (¡cualquier objeto!) Que lo vincule. Es importante por muchas razones de implementación del motor relacionadas con la eficiencia y la recolección de basura, pero también es genial porque permite nuevas semánticas como permisos de acceso revocables y pasar datos sin exponer al remitente de datos.
De MDN :
WeakMaps están disponibles en Firefox, Chrome y Edge actuales. También son compatibles con Node v7, y en v6 con la
--harmony-weak-maps
bandera.fuente
Map
?var m = new Map();m.set({},"abc"); console.log(m.get({}) //=>undefined
Solo funciona si tiene la misma variable a la que hizo referencia originalmente en el comando set. EGvar m = new Map();a={};m.set(a,"abc"); console.log(m.get(a) //=>undefined
La solución que elegí es similar a la de Daniel, pero en lugar de usar una fábrica de objetos y anular toString, agrego explícitamente el hash al objeto cuando se solicita por primera vez a través de una función getHashCode. Un poco desordenado, pero mejor para mis necesidades :)
fuente
Object.defineProperty
laenumerable
serie afalse
, por lo que no se bloqueará ningúnfor .. in
bucles.Para mi situación específica, solo me importa la igualdad del objeto en lo que respecta a las claves y los valores primitivos. La solución que funcionó para mí fue convertir el objeto a su representación JSON y usarlo como hash. Existen limitaciones, como el orden de definición de clave que posiblemente sea inconsistente; pero como dije, funcionó para mí porque todos estos objetos se generaban en un solo lugar.
fuente
Creé un pequeño módulo de JavaScript hace un tiempo para producir códigos hash para cadenas, objetos, matrices, etc. (lo acabo de enviar a GitHub :))
Uso:
fuente
var hash1 = Hashcode.value({ a: 1, b: 2 }); var hash2 = Hashcode.value({ a: 2, b: 1 }); console.log(hash1, hash2);
registrará2867874173
2867874173
La especificación de JavaScript define el acceso a la propiedad indexada como realizar una conversión toString en el nombre del índice. Por ejemplo,
es lo mismo que
Esto es necesario como en JavaScript
es lo mismo que
Y sí, me pone triste también :-(
fuente
En ECMAScript 6 ahora hay una
Set
que funciona como le gustaría: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SetYa está disponible en los últimos Chrome, FF e IE11.
fuente
Referencia: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol
puede usar el símbolo Es6 para crear una clave única y un objeto de acceso. Cada valor de símbolo devuelto por Symbol () es único. Se puede usar un valor de símbolo como identificador para las propiedades del objeto; Este es el único propósito del tipo de datos.
fuente
Aquí está mi solución simple que devuelve un número entero único.
fuente
hashcode({a:1, b:2}) === hashcode({a:2, b:1})
y muchos otros conflictos.Según el título, podemos generar hashes fuertes con js, se puede usar para generar un hash único a partir de un objeto, una matriz de parámetros, una cadena o lo que sea.
Más adelante para indexar esto, evite posibles errores de coincidencia, mientras permite recuperar un índice de los parámetros (evite buscar / recorrer el objeto, etc.):
El resultado anterior en mi navegador, también debería ser igual para usted ( ¿es realmente? ):
https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/digest#Converting_a_digest_to_a_hex_string
fuente
Mi solución introduce una función estática para el
Object
objeto global .Creo que esto es más conveniente con otras funciones de manipulación de objetos en JavaScript.
fuente
Intentaré ir un poco más profundo que otras respuestas.
Incluso si JS tuviera un mejor soporte de hash, no lo haría mágicamente todo perfectamente, en muchos casos tendrá que definir su propia función de hash. Por ejemplo, Java tiene un buen soporte de hashing, pero aún tiene que pensar y hacer algo de trabajo.
Un problema es con el término hash / hashcode ... hay hashing criptográfico y hash no criptográfico. El otro problema es que debes entender por qué el hashing es útil y cómo funciona.
Cuando hablamos de hashing en JavaScript o Java, la mayoría de las veces hablamos de hash no criptográfico, generalmente de hashmap para hashmap / hashtable (a menos que estemos trabajando en autenticación o contraseñas, lo que podrías estar haciendo en el lado del servidor usando NodeJS. ..).
Depende de los datos que tenga y de lo que quiera lograr.
Sus datos tienen alguna singularidad natural "simple":
Sus datos tienen una singularidad natural "compuesta":
No tienes idea de cuáles serán tus datos:
No existe una técnica de hash mágicamente eficiente para datos desconocidos, en algunos casos es bastante fácil, en otros casos puede que tenga que pensar dos veces. Entonces, incluso si JavaScript / ECMAScript agrega más soporte, no hay una solución mágica para este problema.
En la práctica, necesitas dos cosas: suficiente singularidad, suficiente velocidad
Además de eso, es genial tener: "hashcode igual si los objetos son iguales"
fuente
Si realmente desea establecer un comportamiento (me refiero al conocimiento de Java), tendrá dificultades para encontrar una solución en JavaScript. La mayoría de los desarrolladores recomendarán una clave única para representar cada objeto, pero esto es diferente al conjunto, ya que puede obtener dos objetos idénticos, cada uno con una clave única. La API de Java hace el trabajo de verificar valores duplicados al comparar valores de código hash, no claves, y dado que no hay representación de valores de código hash de objetos en JavaScript, se hace casi imposible hacer lo mismo. Incluso la biblioteca Prototype JS admite esta deficiencia, cuando dice:
http://www.prototypejs.org/api/hash
fuente
Además de la respuesta de la falta de párpados, aquí hay una función que devuelve una identificación única y reproducible para cualquier objeto:
Como puede ver, utiliza una lista de búsqueda que es muy ineficiente, sin embargo, eso es lo mejor que pude encontrar por ahora.
fuente
Si desea utilizar objetos como claves, debe sobrescribir su Método toString, como algunos ya se mencionaron aquí. Las funciones hash que se utilizaron están bien, pero solo funcionan para los mismos objetos, no para objetos iguales.
He escrito una pequeña biblioteca que crea hashes a partir de objetos, que puede usar fácilmente para este propósito. Los objetos pueden incluso tener un orden diferente, los hash serán los mismos. Internamente puede usar diferentes tipos para su hash (djb2, md5, sha1, sha256, sha512, ripemd160).
Aquí hay un pequeño ejemplo de la documentación:
El paquete se puede usar en el navegador y en Node-Js.
Repositorio: https://bitbucket.org/tehrengruber/es-js-hash
fuente
Si desea tener valores únicos en un objeto de búsqueda, puede hacer algo como esto:
Crear un objeto de búsqueda
Configurar la función de código hash
Objeto
Formación
Otros tipos
Resultado final
{ 1337: true, 01132337: true, StackOverflow: true }
Tenga en cuenta que
getHashCode
no devuelve ningún valor cuando el objeto o la matriz está vacíaEsto es similar a la solución @ijmacd solo
getHashCode
que no tiene laJSON
dependencia.fuente
Combiné las respuestas de los párpados y KimKha.
El siguiente es un servicio angularjs y admite números, cadenas y objetos.
Ejemplo de uso:
Salida
Explicación
Como puede ver, el corazón del servicio es la función hash creada por KimKha. He agregado tipos a las cadenas para que la estructura del objeto también afecte el valor hash final. Las claves se combinan para evitar colisiones de matriz | objeto.
La comparación de objetos sin párpados se utiliza para evitar una recursión infinita mediante objetos de autorreferencia.
Uso
Creé este servicio para poder tener un servicio de error al que se accede con objetos. Para que un servicio pueda registrar un error con un objeto determinado y otro pueda determinar si se encontraron errores.
es decir
JsonValidation.js
UserOfData.js
Esto devolvería:
Mientras
Esto volvería
fuente
Simplemente use propiedad secreta oculta con el
defineProperty
enumerable: false
Funciona muy rápido :
fuente