El algoritmo SOUNDEX fue concebido teniendo en cuenta la fonética del idioma inglés, por lo que hace inadecuado su uso en el castellano. Realizando adaptaciones propias del idioma español, implementé una versión en PL/SQL llamada SOUNDESP, la cual respeta la esencia del algoritmo original.
Los pasos básicos son:
- Retener la primera letra de la cadena. Tener en cuenta las letras dobles como CH y LL.
- Remover todas las ocurrencias de las letras siguientes a partir de la segunda posición: a, e, i, o, u, h, w, y (cuando suena como vocal i )
- Asignar números a las siguientes letras (luego de la primera):
- b, f, p, v = 1
- c, g, j, k, q, s, x, z = 2
- d, t = 3
- l = 4
- m, n = 5
- r = 6
- ll, y, ch = 7
- Si hay números consecutivos, dejar solamente uno en la serie.
- Retornar los cuatro primeros caracteres, si son menos de cuatro completar con ceros.
SOUNDESP es un proyecto abierto y es bienvenido cualquier comentario para mejorar su implementación.
Ultima versión: 1.8 (04-MAR-2010)
NOTA: Para descargar el código correctamente, haga click derecho y elija Guardar destino
Ver también:
Wikipedia: Soundex
47 comentarios:
Hola,
antes de nada dar las gracias por este package, muy útil, pero le veo un par de bugs así de primeras:
1. Falla si la cadena de entrada es de más de 30 caracteres.
2. Prueba la palabra "Bahía" verás que falla porque elimina la H y las vocales y nos quedamos con una palabra de una letra que falla en la función eli_ady
Espero sea de utilidada
¿Lo vas a solventar?
Gracias
Roberto, ya fueron solucionados esos bugs, la nueva versión ya está disponible.
Muchas gracias y cualquier otro comentario será más que bienvenido!
Saludos
Gracias por la rapidez.
Se me olvidó comentar un fallo que corregí sobre la marcha, he tenido que modificar la función eli_acc para que funcione con algunos casos por esta:
FUNCTION eli_acc(p_pal IN VARCHAR2) RETURN VARCHAR2 AS
BEGIN
RETURN TRANSLATE(LTRIM(UPPER(p_pal),'H'),'ÑñáéíóúÁÉÍÓÚ','NNAEIOUAEIOU');
END eli_acc;
Espero sea de utilidad.
Saludos
Aunque lo más correcto sería esto:
FUNCTION eli_acc(p_pal IN VARCHAR2) RETURN VARCHAR2 AS
BEGIN
RETURN TRANSLATE(LTRIM(UPPER(p_pal),'H'),'ÑÁÉÍÓÚ','NAEIOU');
END eli_acc;
ya que está en mayúsculas el convertir las minúsculas carece de sentido.
Saludos
Creo que esto no acaba de ir del todo bien, estoy probandolo con diversas cadenas y me da resultados de lo más extraños. Fijate:
Aldeyuso|A437
Aguilar de Campos|AG46
Aguilar de Campos|AG46
La Abadía|L 13
Abrojo|A167
Los Álamos|L2 4
Los Álamos|L2 4
Aceñas de Zofraguillas|A252
Las Aceñas|L2 2
Se supone que los resultados deberían tener el formato \w\d{3}
Estoy un poco pesadito, pero gracias a esto podemos conseguir un package muy sólido.
Te comento otra cosa, cuando pasamos una cadena de 30 caracteres o más sin ningún tipo de acento como por ejemplo:
'Esto es una prueba de mas de 30 caracteres'
Todo va bien, pero surge un problema cuando uno o varios de esos caracteres en los primeros 30 está acentuado porque ese caracter ocupa 2 bytes, por ejemplo:
'Esto es una prueba de más de 30 caracteres'
He acentuado la 'a' de más y claro ahora al cortar y quedarlo en 30:
'Esto es una prueba de más de 3'
Internamente están contando 31 y falla, por lo cual habría que hacer una de estas opciones:
a) Quitar los acentos antes de cortar la cadena.
b) Tener en cuenta que la cadena medirá 30 + número de caracteres especiales.
Espero que sirva.
Saludos
Roberto, muy valiosos comentarios,
hay una nueva versión disponible que corrige lo siguiente:
- Tomo tu sugerencia sobre TRANSLATE en eli_acc y además elimino espacios para evitar resultados como los que reportaste
- Elimino caracteres multibyte antes de cortar a 30 la cadena de caracteres tal como sugieres
Gracias y saludos!
Amigos no se si será por mi desconocimiento de la fonética de nuestro idioma pero me parece que en la función
cnv_dos se debería remplazar la LL por Y de esta forma seria lo mismo YANDER que LLANDER.
corríjanme si me equivoco.
Es muy correcto, y quedó corregido ese detalle. Ahora YANDER y LLANDER retornan el mismo valor.
Muchas gracias!
Saludos
Quisiera que me explicaran cual es la idea de retener la primera letra y luego concatenársela a la cadena final,que se logra con esto??.
Hola chicos, lamento decirles que no funciona para el siguiente listado de palabras:
abakuá,avakuá,abacuá,avacuá,
habakuá,havakuá,habacuá,havacuá
en todos los casos el resultado rebería ser el mismo porque foneticamente las palabras son !exactas!
Quisiera que me explicaran cual es la idea de retener la primera letra y luego concatenársela a la cadena final,que se logra con esto??.
La verdad que no tiene importancia. Recuerda que este algoritmo surgió para censar nombres, así que me imagino que era una forma de tener las tarjetas perforadas ordenadas por la letra inicial.
Igual sucede con la cantidad de letras que produce el cod. originalmente 4 (A567) es debido al promedio de la palabra anglosajona y de las cantidad de letras que se eliminan, para el caso del español podría ser mayor.
abakuá,avakuá,abacuá,avacuá,
habakuá,havakuá,habacuá,havacuá
Está arreglado el bug, v y b no estaban asociados según el algoritmo.
Ahora todas las cadenas retornan A120.
Gracias!
Saludos
Excelente proyecto!
Lo he migrado a PHP de forma muy básica.
Comparto con ustedes el link para descargarlo: http://rapidshare.com/files/170388402/SoundEsp.class.php.zip.html
Saludos,
Rodrigo Muñoz.-
Gracias por el trabajo.
En la version on-line de test obtengo errores al introducir Barcèlona o María.
Sugiero que trabaje con algunas tildes como à è ò que no son del español pero si usadas en territorio español en otras lenguas.
Tambien esta la ele "geminada" "l·l" que en la practica suena como una ele (el punto es el que sale con Shift-3 en un teclado español, aunque muchas veces se escribe como punto normal)
Ops, y la "ny" que suena como una eñe, puestos a pedir ;-)
Se arregló el problema de los acentos de la applicación en test, ahora está funcionando correctamente.
Domenec:
De forma que este proyecto sea útil a la mayoría de las personas, hemos establecido un marco que contempla los caracteres y pronunciación neutra del castellano únicamente.
No es mi objetivo abarcar todas las variaciones regionales ni influencias de otros idiomas, sino lograr un código de base.
El paquete está disponible para que cualquiera pueda modificarlo a su gusto, por ejemplo para incluir los acentos que mencionas, o adaptarlo a la pronunciación de su territorio.
Como compensación, te acepto la traducción del sonido ny como ni, por no ofrecer conflicto en la mayoría de los países de habla hispana. :)
Gracias por tu aporte!!
Saludos
Excelente trabajo me han salvado la vida... si me sale este negocio quiero hacerles una donacion a los creadores.... jejejje
Una consulta:
Alguien de ustedes conoce una funcion similar para analisis de palabras que tienen errores tipograficos basados en las posiciones de las teclas en el teclado... es parecido a la funcion que crearon.. por ejemplo:
tierra = rierra por que la R esta al lado de la letra T en el teclado.
Muchisimas gracias por tu paquete!
Yo lo implementé para buscar una frase con varios nombres en otra frase con varios nombres.
Ej. "Juan Perez" en "Juan Antonio Perez Lopez"
Analicé cada palabra de la primera frase en cada palabra de la segunda frase. Dependiendo del porcentaje de palabras de la primera frase que estuvieran en la segunda devolvia exito.
saludos!
hola pues primero te felicito
muy buen aporte, lo iba a pasa ra mysql pero no tengo mucha experiencia escribiendo funciones en mysql, de momento lo pase a ruby y parece estar funcionando igual, me genero algunas dudas la parte de
traslate(p_pal, '@AEIOUHWY','@')
que no entendi bien lo de la @ y termine cambiando las arrobas por '' y los ' ' por '' y parece ir ahora todo bien.
si alguien le interesa el codigo me lo hace saber.
no esta tan bien pensado hacia ruby solo me dedique a transcribirlo pero funciona.
les dejo mi correo si alguien les interesa.
omar.omarseb@gmail.com
Que tal tengo una duda, he estado probando el algoritmo desde la pagina y por ejemplo si ingreso Vasquez o Bazques me da el mismo resultado B200 eso esta bien, pero si ingreso Valle y Baye me da el mismo resultado B200 tambien, no se que puedo hacer para que esta parte me retorne resultados distintos, o si ese era el funcionamiento esperado. Gracias.
Hola,
El caso de Valle y Baye es sutil y depende un poco de la región. En el Rio de la Plata, el Caribe o España, esa sílaba puede tener diferente sonido. En ese caso, es preferible dar el mismo valor equivalente.
De todas formas, si deseas personalizar el código puedes alterar la funcion cnv_dos dentro del paquete, y asignar una letra diferente a la sílaba YE.
Espero que te sirva.
Un abrazo
Gracias por la pronta respuesta solo que creo que expuse mal mi pregunta. Mi dura era que parte del código podría modificar para que Basquez y Valle me den resultados distintos, porque intente con lo que me dijiste de modificar la silaba “YE” pero creo que no he entendido el funcionamiento de la rutina cnv_dos, perdón por tanta pregunta.
Hola,
Gracias por tu valioso aporte, he subido otra versión corrigiendo un error de conversión. Puede ser que solucione tu problema.
Saludos
Gracias lo he estado testeando y si esta perfecto, gracias por la ayuda.
La tabla de conversión expuesta en el paso básico número 3 no está actualizada conforme al código vigente de la aplicación.
Por lo demás, me ha sido muy útil para mi propia rutina (en ASP VbScript, para aplicarla próximamente en la rutina de búsqueda interna de mi sitio web).
Muchas gracias.
Hola lfer.
Antes que nada gracias por tu blog y en especial por este package que espero me sea útil (Estoy evaluando todavía si este es el camino por el que quiero que vaya mi proyecto).
He detectado que con ciertas combinaciones con la letra G el resultado que devuelve no está en el formato A000. Te dejo unos ejemplos: MAGUFO - MG10, MANGANTE - M5G5, SUBMAGO - S15G.
No he mirado mucho pero creo que tiene que ver con la funcion map_num que no asigna equivalencia numérica a la G.
Gracias!!
Akinet, he corregido el bug, muchas gracias por el aporte! Acertaste en acusar a la funcion map_num :)
Ya está disponible para descargar en el link arriba.
Saludos
Basarse en el codigo en ingles SOUNDEX, me parece que ya esa arrastar un erro de concepcion fonetica, por ejemplo segun tu codigo "Alicante" es igual que "Aliciente", con el codigo A425, cuando una sonaria "alikante" y la otra sonaria "alisiente", considero que el codigo debe ser realizado desde cero, y no basandose en el codigo anglosajón, porque asignar a la c un solo valor cuando puede sonar como S o como K es un error grave
Agradezco tu comentario y no comparto tu ejemplo. No pasa por ser inglés o castellano, el propio algoritmo SOUNDEX iguala los fonemas 'S' y 'C' (o K), eso es independiente del idioma. Tanto 'acronym' como 'asteroid' asignan un valor 2 en su segunda posición.
Bien es sabido que SOUNDEX tiene sus limitaciones y no es perfecto, pero no era mi intención arreglarlo sino implementar precisamente, SOUNDEX.
Hola que tal
Creo que encontré otro bug que tiene que ver con letras iguales al principio. por ejemplo vaca y vvaca, juan y jjuan. Cada pareja debería arrojarme el mismo resultado.
saludos y gracias por el paquete
Una observación: el algoritmo Soundex en su definición más conocida no indica un tratamiento de errores tipográficos de las cadenas de entrada, tales como consonantes dobles, espacios, o símbolos no alfanuméricos.
Teniendo esto en cuenta, las palabras "vvaca" y "vaca" deberían tener diferente codificación si seguimos las reglas basicas, ya que la segunda consonante luego de la primera es 'v'(=1) en el primer caso y 'c'(=0) en el segundo.
La implementación de Oracle aparentemente tiene un tratamiento de la cadena para este tipo de casos, pero sería una característica extra algoritmo.
Me parece buena idea agregar ese "accesorio" para acercarnos lo más posible a la función de Oracle.
Próximamente estaré disponibilizando una nueva versión.
Gracias por la contribución!
Saludos
Hola, buenos aportes pero quisiera saber porq sale q es igual 'cemento' y 'zenda'
Si yo también probé Cemento con Zenda y los resultados indican que son iguales.
Hola,
muchas gracias por tu código. Ha sido de gran ayuda.
Creo que ayudaría en la búsqueda fonética, convertir los números a palabras:
1 = UNO
2 = DOS
...
22= VEINTIDOS O VEINTE Y DOS
...
Saludos,
Hola!
Antes que nada, felicitaciones por la publicación, es muy interesante, de hecho, lo he adaptado a un proyecto en otro lenguaje.
Sin embargo, he detectado que para algunas palabras produce el mismo resultado, por ejemplo:
"Nacional" y "Nacionalidad" lo mismo ocurre con palabras cortas como "ley" y "la".
Un cordial saludo,
Estimado, buenas tardes: mi nombre es Luciano, trabajo buscando coincidencias de nombres, quería saber cómo se puede "ajustar" un poco más el parámetro de búsqueda de coincidencia. Por ejemplo, si comparo a JOSE LUIS GONZALEZ IBAÑEZ contra JOSE LUIS IBAÑEZ MIÑO que no haya coincidencia entre ellos porque son personas distintas. Otro ejemplo: MARIA DEL CARMEN GONZALEZ CONTRA MARIA DEL ROSARIO GONZALEZ. ¿se podría ajustar el parámetro o porcentaje de coincidencia?
Hola e implementado un algoritmo propio basandome en el soundesp y me esta funcionando bien. Tal vez me podrian ayudar a hacerlo mas robusto. donde prodria publicar el algoritmo (esta en MSQL) pero es facil de convertir a oracle.
mi correo es eampuerog@gmail.com
Gracias por el aporte. En Sql Server hay una función que se llama Difference, que devuelve un valor numérico de 0 a 4, el 4 significa que dos cadenas comparadas son iguales o casi iguales. Como aplico esto aquí. Como hago una comparación entre dos cadenas, como sé que son iguales o casi iguales??? Shuwer David L
Hola. El algoritmo funciona mejor. Necesito detalles sobre tí, para incluirlo como una cita de autor de la versión SOUNDESP en mi tesis de grado sobre coincidencia de nombres. Es especialmente bueno en el tratamiento que hace de las letras combinadas con el sonido de la CH y la LL. Te he enviado un correo al gmail. Gracias.
Delgado Juan C.
@lfer: gracias por este gran aporte a la informática hispana.
@Domenec: has conseguido implementar el SOUNESP para el catalá?
Yo creo que como es una lengua que difiere de manera considerable al español (ya que el catalán no es una variante del español (si del latín), sino más bien una mezcla de 5 idiomas, español, francés, portugués, italiano y rumano.
Valdría la pena modificar SOUNDESP, para hacer un SOUNDCAT???
O una variante de SOUNDESP en donde pueda recibir un parametro de la cultura o variante, por ejemplo: CA, EU, GA (Catalán, Euskera, Gallego).
Que opinan?
Yo podría buscar implementar para catalán, pero no soy catalán, ni muy experto en PL-SQL, aunque no parece muy complicado el código. Soy mexicano, así que agradecería mucho alguna ayuda de un parlante catalán que conozca bien las reglas de pronunciación.
Saludos y nuevamente muchas gracias @lfer por este GRAN GRAN aporte.
Hola me he encontrado que morada, mareada, mirada, mierda, muerda dan el mismo resultado M630... no sé si asi debe ser. Gracias y saludos
Busca por Metaphone, es la version en ingles mejorada por mucho! =D
http://aspell.net/metaphone/metaphone-kuhn.txt
Desarrollé un Fonetizador 100% en español hace ya algunos años, se usó para fonetizar la base de datos del Buró de credito en Mx sobre mas de 15 MILLONES DE REGISTROS DE TARJETAHABIENTES! y sigue vigente. Es para identificar nombres de personas o calles!, lo migraré a VB y esta a la venta ;-)
avaz6677@gmail.com
Saludos.
El SundEsp ya esta listo y funcionando perfecto (en VB y C), sobre Nombres y Apellidos en Español, incluso sobre cadenas complejas o largas, como pueden ser direcciones, ej:
del arbol kaido en vataya E2B 1FP4B 713E4 2K P1M1I1
Del árbol caido en batalla E2B 1FP4B 713E4 2K P1M1I1
El alfabeto español se constituye de 27 letras únicamente, 22 consonantes, 5 vocales, y 5 Dígrafos. Los casos como ch, ll, rr, qu y gu (sh) son considerados DIGRAFOS, es decir, un grupo de dos letras que representan un solo sonido.
Ejemplos de Fonetizador en español (palabras, código fonético):
ABAKUA AVAKUA ABACUA AVACUA HABAKUA HAVAKUA HABACUA HAVACUA
1P1751 1P1751 1P1751 1P1751 1P1751 1P1751 1P1751 1P1751
ACUAMAN AQUAMAN AKUAMAN
1751J1K 1751J1K 1751J1K
QUIQUE KIKE
7372 7372
ENRIQUE HENRIKE HENRIQUE
2KF372 2KF372 2KF372
HERNANDEZ HERNANDES ERNANDES ERNANDEZ
2FK1KE26 2FK1KE26 2FK1KE26 2FK1KE26
GUILLEN GUIYEN GUEVARA GEVARA
A3I2K A3I2K A2P1F1 92P1F1
AREBOLA ARREBOLA
1F2P4B1 1R2P4B1
CASTAÑEDA MAGAÑA CASTAÑON CASTAÑA
716M1H2E1 J1A1H1 716M1H4K 716M1H1
El algoritmo de fonetización SoundEsp (Soundex en Español), es muy útil de implementarse en grandes Bases de Datos privadas, principalmente por Bancos y empresas dedicadas al análisis y otorgamiento crediticio y servicios financieros; como tiendas departamentales, telefonía celular, créditos hipotecarios, Cajas Populares y de Ahorro, etc., con la finalidad de ayudar a mitigar, reducir y controlar de mejor manera los riesgos en el otorgamiento de créditos al publico en general, mejorando en gran medida la toma de decisiones corporativa.
Búscame en FB: https://www.facebook.com/Fonetizador-en-Espa%C3%B1ol-Soundex-1609415286018889/?ref=ts&fref=ts
Saludos.
Ya merito! =D
http://soundesp.somee.com/Fonetizador.asp
Saludos.
Publicar un comentario