es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Convertir cadenas a enteros UTF de 16 bits en Javascript.

Estoy trabajando con Firebase Firestore y por alguna razón necesito convertir cada nuevo documento de usuario a un ID entero, específicamente a un entero UTF de 16 bits. Mayormente estoy tratando de duplicar el método .hashcode en Dart.

Lo que he encontrado y probado es lo siguiente:

// Convertir a entero de 32 bits
const hashFunction = (string) => {
  var hash = 0;
  if (string.length == 0) return hash;

  for (i = 0; i < string.length; i++) {
    char = string.charCodeAt(i);
    hash = (hash << 5) - hash + char;
    hash = hash & hash;
  }
  return hash >>> 0;   // retorna el hash como un entero positivo
};

Pero esto solo convierte a un entero de 32 bits. Cualquier ayuda será apreciada.

EDIT1: Usando los cambios de @selbie, he progresado un poco pero el hash que obtengo es bastante diferente al método .hashCode en Dart. Aquí está la salida de Dart y aquí está la salida en JS.

¿Hay alguna forma de obtener el mismo resultado?

Tags:  , , , ,

Answer

  1. Avatar for davy.ai

    Parece que estás tratando de hashear cada ID de documento de nuevo usuario a un entero UTF de 16 bits utilizando Javascript para Firebase Firestore. El código que proporcionaste solo convierte a un entero de 32 bits, lo cual no es lo que necesitas.

    Una opción que podrías intentar es modificar la función de hash actual para que solo devuelva los 16 bits inferiores del entero de 32 bits. Esto se puede lograr utilizando una operación a nivel de bit, de la siguiente manera:

    const hashFunction = (string) => {
      var hash = 0;
      if (string.length == 0) return hash;
    
      for (i = 0; i < string.length; i++) {
        char = string.charCodeAt(i);
        hash = (hash << 5) - hash + char;
        hash = hash & hash; // igual que: hash = hash % 2^32;
      }
      // devuelve solo los 16 bits inferiores
      return hash & 0xffff;
    };
    

    Esto debería devolver un entero sin signo de 16 bits (0 a 65535) según se requiere.

    Sin embargo, parece que la salida de tu implementación actual es diferente al método .hashCode en Dart. Una razón podría ser la diferencia de codificación entre UTF-16 (utilizado por Javascript) y UTF-8 (utilizado por Dart).

    Una posible solución podría ser utilizar la API TextEncoder en Javascript para convertir la cadena en un ArrayBuffer codificado en UTF-8, y luego hashear este ArrayBuffer en su lugar. Así es cómo podrías modificar tu código para esto:

    const hashFunction = (string) => {
      var hash = 0;
      if (string.length == 0) return hash;
    
      // convierte la cadena en un ArrayBuffer codificado en UTF-8
      const encoder = new TextEncoder();
      const buffer = encoder.encode(string);
    
      for (i = 0; i < buffer.byteLength; i++) {
        char = buffer[i];
        hash = (hash << 5) - hash + char;
        hash = hash & hash; // igual que: hash = hash % 2^32;
      }
      // devuelve solo los 16 bits inferiores
      return hash & 0xffff;
    };
    

    Esto debería darte la misma salida de hash que el método .hashCode en Dart.

Comments are closed.