2011-04-18 9 views
14

Używam wyszukiwania opartego na AJAX dla nazw, które użytkownik wyszukuje w polu tekstowym.Używanie JavaScript do wykonywania dopasowań tekstowych z/bez znaków akcentowanych

Przyjmuję założenie, że wszystkie nazwy w bazie danych będą transliterowane do europejskich alfabetów (tj. Bez cyrylicy, japońskiego, chińskiego). Jednak nazwy będą nadal zawierać znaki akcentowane, takie jak ç, ê, a nawet č i ć.

Proste wyszukiwanie, takie jak "Micic", nie będzie jednak pasować do "Mičića" - a oczekiwaniem użytkownika jest to, że tak będzie.

Wyszukiwanie AJAX używa wyrażeń regularnych do określenia dopasowania. Zmodyfikowałem porównanie wyrażeń regularnych, używając tej funkcji, aby dopasować więcej znaków akcentowanych. Jest to jednak trochę niezgrabne, ponieważ nie uwzględnia wszystkich postaci.

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; 
} 

Oprócz takiej funkcji zastępowania istnieje lepszy sposób? Być może do "pomarszczenia" porównywalnej struny?

+0

Dzięki za kod, użyłem twojej funkcji, aby zastąpić akcentowane samogłoski w tekście wejściowym i działało poprawnie. – IgniteCoders

Odpowiedz

0

pierwsze, polecam instrukcji switch zamiast długi ciąg if-else if ...

Następnie Nie wiem, dlaczego nie lubisz swojego obecnego rozwiązania. Z pewnością jest najczystszym. Co masz na myśli, nie biorąc pod uwagę "wszystkich postaci"?

W języku JavaScript nie ma standardowej metody odwzorowywania liter akcentowanych na litery ASCII poza biblioteką stron trzecich, więc ta, którą napisałeś, jest równie dobra jak inna.

Również "ß" uważam, że mapy "ss", a nie pojedyncze "s". I uważaj na "i" z i bez kropki w języku tureckim - uważam, że odnoszą się do różnych liter.

+0

Wolałbym opcję 'haystack.indexOfIgnoreAccents (needle)' :) Nie lubię robić ciężkich podnoszenie ... – Philip

6

Nie ma łatwiejszego sposobu na „deaccent”, że mogę myśleć, ale twój substytucja może być usprawnione trochę więcej:

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

To z pewnością bardziej elegancka wersja mojej funkcji. – Philip

1

zrobiłem prototyp wersja tego:

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];}) 
    ); 
}; 

wykorzystanie takich jak:

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

Ta wola zmieni String do a_o_u_A_O_U_ss

1

Szukałem czegoś podobnego, ale zamiast tworzyć wyrażenie regularne chciałem tylko zamienić znaki akcentowane na ich odpowiedniki ASCII. Zainspirowany odpowiedzią 999 i artykułem w A List Apart (http://www.alistapart.com/articles/accent-folding-for-auto-complete/) przyszedł mi następująca funkcja. To może być modyfikowana dla konkretnych wdrożeń kursu:

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; 
    }; 
}()); 

Wykorzystanie:

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

przyszedł na tym starym wątku i pomyślałem, że spróbować swoich sił w sposób szybki funkcję. Opieram się na porządkowaniu zmiennych OR ustawiających zmienne, gdy pasują one do funkcji replace().Moim celem było użycie standardowej implementacji regex javascript funkcja replace() wykorzystuje jak najwięcej, tak aby ciężkie przetwarzanie mogło odbywać się w przestrzeni zoptymalizowanej pod kątem niskiej przeglądarki, zamiast w kosztownych javascriptowych porównaniach char-by-char .

To nie jest naukowa w ogóle, ale mój stary Huawei IDEOS android telefon jest słaby kiedy podłączam inne funkcje w tym wątku w moim autouzupełniania, podczas gdy funkcja ta zamki wzdłuż:

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'; }); 
} 

Jeśli jesteś jQuery dev, oto przydatny przykład użycia tej funkcji; można użyć: icontains taki sam sposób byłoby użyć: zawiera w selektora:

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