Páginas

lunes, 14 de enero de 2019

Función hash en JavaScript y PHP para convertir cadena de texto a número

Hash  Hace un par de días me vi en la necesidad de representar una cadena de texto como un valor numérico para obtener un identificador. Las funciones hash MD5, SHA1 y otras similares harían esto sin problemas; solo que hay un detalle: estas funciones retornan la cadena codificada pero incluyen números y letras en su estructura, yo necesitaba números, además de que ese número no fuera muy largo pues al guardarlo en una base de datos como numérico, si es muy largo se truncaba. Así que después de investigar un rato encontré una función útil que quiero compartir con ustedes. La función original está en JavaScript, pero también hice su adaptación para PHP, espero les sea de utilidad.
Publicidad


  Una función hash es una función que permite resumir un dato, si nosotros ingresamos una cadena de texto muy larga obtendremos una fotografía de ella pero como una secuencia de números y letras en un tamaño mucho más compacto,1  bueno, eso era precisamente lo que necesitaba, convertir un ID en formato texto (números y letras), pero tener su equivalente como número.

 Para ello vamos a ver como trabaja la siguiente función que encontré en https://medium.com/laboratoria-how-to/como-declarar-tu-amor-con-hash-tables-bfad01005fa9 y por este medio aprovecho para darle las gracias al autor, me ha sido de mucha ayuda su aporte.

//thanks to https://medium.com/laboratoria-how-to/como-declarar-tu-amor-con-hash-tables-bfad01005fa9
function stringToHash(str)
{

    var cont = 0;

    str.split("").forEach(function(letter){
        cont += letter.charCodeAt(0)
    });
    
    return cont;
    
}

  La función stringToHash recibe un parámetro representado por el nombre str, el valor de ese parámetro se divide en todos los caracteres mediante la función split y posteriormente mediante un ciclo asociado va leyendo esos caracteres y los convierte a su equivalente ASCII (letter.charCodeAt(0)) para finalmente sumar esa valor al contenido previo del contador (cont).

  Si todo sale bien, ahora cont tiene la suma de todos los caracteres ingresados pero en formato ASCII.

  De manera que si ingresáramos el texto "Hello world!" la función nos retornaría el valor 1117, tal como vemos en la prueba:
Función hash en JavaScript
Este es el código fuente completo:

<script language="JavaScript">

alert(stringToHash("Hello world!"));

//thanks to https://medium.com/laboratoria-how-to/como-declarar-tu-amor-con-hash-tables-bfad01005fa9
function stringToHash(str)
{

    var cont = 0;

    str.split("").forEach(function(letter){
        cont += letter.charCodeAt(0)
    });
    
    return cont;
    
}

</script>

  Solo una aclaración: esta función no es resistente a colisiones, sin ingresáramos otro texto, por ejemplo "Hello world!" invertido obtendríamos el mismo resultado. La finalidad de esta función fue solo representar un dato como número, pero dicho valor ya ha sido generado previamente como dato único, por lo que no tengo problemas de colisiones (por el momento).

Ahora veamos como podemos implementar la misma función pero en PHP.

<?

echo stringToHash("Hello world!");


//Inspirated in https://medium.com/laboratoria-how-to/como-declarar-tu-amor-con-hash-tables-bfad01005fa9
function stringToHash($str)
{

  $cont = 0;

  for($i=0; $i<strlen($str); $i++)
    $cont = $cont + (int)ord(substr($str, $i, 1));

  return $cont;
    
}

?>

 El funcionamiento es prácticamente el mismo, la función stringToHash recibe un parámetro por medio de la variable $str, se va extrayendo caracter por caracter desde la variable $str y al mismo tiempo mediante la función ord se obtiene su equivalente en código ASCII. Dicho valor ya transformado se suma al contenido previo de la variable $cont, esto provoca que al final $cont contenga la suma de toda la cadena y finalmente retornamos el resultado.
Función hash en PHP
 Espero les halla sido de mucha utilidad.

Procedencia de las imágenes:

1.- Función hash

 ¿Te gustó este post?, entonces si lo deseas puedes apoyarnos para continuar con nuestra labor, gracias.

6 comentarios:

  1. Generalmente usar iteradores es una mala idea, siempre son lentos y consumen más memoria, yo lo implementaría en ECMAScript más plano:

    "use strict";

    alert(stringToHash("Hello world!"));


    function stringToHash(psString)
    {
    let iHash = 0;
    let iLen = psString.length;

    for (let iCont = 0; iCont < iLen; iCont++)
    {
    iHash += psString.charCodeAt(iCont);
    }
    return(iHash);
    }


    Pruébalo y verás como es muchísimo más veloz.

    ResponderBorrar
  2. Que tal:

    Estoy probando lo que me sugeriste, pero al ver la diferencia entre los dos scripts en cuestión de tiempo de ejecución, a los dos les toma "0" segundos terminar (Chrome). ¿Hay alguna manera de medir el rendimiento entre los dos que no sea por una diferencia de tiempos?, gracias, muchos saludos.

    ResponderBorrar
  3. Lo que yo hice fue hacer que se ejecutase varias veces y medir el tiempo total. Algo así:

    var i;
    for (i=0; i<100; i++)
    {
    console.log(stringToHash("Hello world!"));
    }

    ResponderBorrar