2011-04-18 6 views
14

Estoy usando una búsqueda basada en AJAX para los nombres que un usuario busca en un cuadro de texto.Uso de JavaScript para realizar coincidencias de texto con/sin caracteres acentuados

Supongo que todos los nombres de la base de datos se transcribirán en alfabetos europeos (es decir, no cirílico, japonés, chino). Sin embargo, los nombres seguirán conteniendo caracteres acentuados, como ç, ê e incluso č y ć.

Sin embargo, una búsqueda simple como "Micic" no coincidirá con "Mičić", y la expectativa del usuario es que sí lo hará.

La búsqueda AJAX utiliza expresiones regulares para determinar una coincidencia. Modifiqué la comparación de expresión regular usando esta función en un intento de hacer coincidir más caracteres acentuados. Sin embargo, es un poco torpe ya que no toma en cuenta todos los personajes.

function makeComp (input) 
{ 
    input = input.toLowerCase(); 
    var output = ''; 
    for (var i = 0; i < input.length; i ++) 
    { 
     if (input.charAt (i) == 'a') 
      output = output + '[aàáâãäåæ]' 
     else if (input.charAt (i) == 'c') 
      output = output + '[cç]'; 
     else if (input.charAt (i) == 'e') 
      output = output + '[eèéêëæ]'; 
     else if (input.charAt (i) == 'i') 
      output = output + '[iìíîï]'; 
     else if (input.charAt (i) == 'n') 
      output = output + '[nñ]'; 
     else if (input.charAt (i) == 'o') 
      output = output + '[oòóôõöø]'; 
     else if (input.charAt (i) == 's') 
      output = output + '[sß]'; 
     else if (input.charAt (i) == 'u') 
      output = output + '[uùúûü]'; 
     else if (input.charAt (i) == 'y') 
      output = output + '[yÿ]' 
     else 
      output = output + input.charAt (i); 
    } 
    return output; 
} 

Aparte de una función de sustitución como esta, ¿hay una mejor manera? ¿Tal vez para "desacralizar" la cadena que se compara?

+0

Gracias por el código, utilicé su función para reemplazar las vocales acentuadas en el texto de entrada y funcionó bien. – IgniteCoders

Respuesta

0

En primer lugar, me gustaría recomendar una sentencia switch en lugar de una larga cadena de

if-else if ...

Entonces, No estoy seguro de por qué no le gusta su solución actual. Sin duda es el más limpio. ¿Qué quieres decir con no tener en cuenta "todos los personajes"?

No hay un método estándar en JavaScript para asignar letras acentuadas a letras ASCII fuera de utilizar una biblioteca de terceros, por lo que la que usted escribió es tan buena como cualquiera.

Además, "ß" creo mapas en "ss", ni una sola "s". Y ten cuidado con "yo" con y sin punto en turco, creo que se refieren a letras diferentes.

+0

Preferiría una opción 'haystack.indexOfIgnoreAccents (needle)' :) No me gusta tener que hacer el pesado levantando ... – Philip

6

No hay manera más fácil de "deaccent" que se me ocurre, pero su sustitución podría ser simplificado un poco más:

var makeComp = (function(){ 

    var accents = { 
      a: 'àáâãäåæ', 
      c: 'ç', 
      e: 'èéêëæ', 
      i: 'ìíîï', 
      n: 'ñ', 
      o: 'òóôõöø', 
      s: 'ß', 
      u: 'ùúûü', 
      y: 'ÿ' 
     }, 
     chars = /[aceinosuy]/g; 

    return function makeComp(input) { 
     return input.replace(chars, function(c){ 
      return '[' + c + accents[c] + ']'; 
     }); 
    }; 

}()); 
+0

Esta es ciertamente una versión más elegante de mi función. – Philip

1

Hice una versión prototipo de esta:

String.prototype.strip = function() { 
    var translate_re = /[öäüÖÄÜß ]/g; 
    var translate = { 
    "ä":"a", "ö":"o", "ü":"u", 
    "Ä":"A", "Ö":"O", "Ü":"U", 
    " ":"_", "ß":"ss" // probably more to come 
    }; 
    return (this.replace(translate_re, function(match){ 
     return translate[match];}) 
    ); 
}; 

uso como:

var teststring = 'ä ö ü Ä Ö Ü ß'; 
teststring.strip(); 

Esta voluntad se cambie la cadena a a_o_u_A_O_U_ss

1

Estaba buscando algo similar, pero en lugar de crear una expresión regular solo quería reemplazar los caracteres acentuados por sus equivalentes ASCII. Inspirado por la respuesta de 999 y un artículo en A List Apart (http://www.alistapart.com/articles/accent-folding-for-auto-complete/), llegué con la siguiente función. Puede ser modificado para las implementaciones específicas del curso:

var accent_fold = (function() { 
    var accent_map = { 
     'à': 'a', 'á': 'a', 'â': 'a', 'ã': 'a', 'ä': 'a', 'å': 'a', // a 
     'ç': 'c',             // c 
     'è': 'e', 'é': 'e', 'ê': 'e', 'ë': 'e',      // e 
     'ì': 'i', 'í': 'i', 'î': 'i', 'ï': 'i',      // i 
     'ñ': 'n',             // n 
     'ò': 'o', 'ó': 'o', 'ô': 'o', 'õ': 'o', 'ö': 'o', 'ø': 'o', // o 
     'ß': 's',             // s 
     'ù': 'u', 'ú': 'u', 'û': 'u', 'ü': 'u',      // u 
     'ÿ': 'y'             // y 
    }; 

    return function accent_fold(s) { 
     if (!s) { return ''; } 
     var ret = ''; 
     for (var i = 0; i < s.length; i++) { 
      ret += accent_map[s.charAt(i)] || s.charAt(i); 
     } 
     return ret; 
    }; 
}()); 

uso:

var someText = "lôõk mä, nø hånds!"; 
someText = accent_fold(someText); 
// someText now contains: "look ma, no hands!" 
10

encontré con este viejo hilo y que me gustaría probar mi mano en hacer una función rápida. Estoy confiando en el orden de las variables de configuración de ORs separadas por tubería cuando coinciden en la función que replace() está llamando.Mi objetivo era utilizar la versión estándar de Regex. La función de reemplazo de javascript usa tanto como sea posible, para que el procesamiento pesado pueda tener lugar en un espacio de bajo nivel optimizado para el navegador, en lugar de costosas javascript char-by-carbon. .

No es científico en absoluto, pero mi viejo teléfono Android Huawei IDEOS es lenta cuando conecto las otras funciones de este hilo a mi autocompletar, mientras esta función cremalleras a lo largo de:

function accentFold(inStr) { 
    return inStr.replace(/([àáâãäå])|([ç])|([èéêë])|([ìíîï])|([ñ])|([òóôõöø])|([ß])|([ùúûü])|([ÿ])|([æ])/g, function(str,a,c,e,i,n,o,s,u,y,ae) { if(a) return 'a'; else if(c) return 'c'; else if(e) return 'e'; else if(i) return 'i'; else if(n) return 'n'; else if(o) return 'o'; else if(s) return 's'; else if(u) return 'u'; else if(y) return 'y'; else if(ae) return 'ae'; }); 
} 

Si eres un desarrollador de jQuery, aquí hay un ejemplo práctico del uso de esta función; usted podría utilizar: icontains de la misma manera que tendría que utilizar: contiene en un selector:

jQuery.expr[':'].icontains = function(obj, index, meta, stack){ return accentFold((obj.textContent || obj.innerText || jQuery(obj).text() || '').toLowerCase()).indexOf(accentFold(meta[3].toLowerCase())) >= 0; }; 
Cuestiones relacionadas