使用JavaScript执行带/不带重音字符的文本匹配

使用JavaScript执行带/不带重音字符的文本匹配,javascript,string,collation,non-ascii-characters,Javascript,String,Collation,Non Ascii Characters,我使用的是基于AJAX的名称查找,用户在文本框中搜索这些名称 我假设数据库中的所有名称都将被音译为欧洲字母(即没有西里尔文、日文、中文)。然而,这些名字仍将包含重音字符,如ç、ê和偶č和ć 不过,像“Micic”这样的简单搜索将无法与“Mičić”匹配——用户的期望是它会匹配 AJAX查找使用正则表达式来确定匹配项。我使用这个函数修改了正则表达式比较,试图匹配更多的重音字符。但是,它有点笨拙,因为它没有考虑所有角色 function makeComp (input) { input =

我使用的是基于AJAX的名称查找,用户在文本框中搜索这些名称

我假设数据库中的所有名称都将被音译为欧洲字母(即没有西里尔文、日文、中文)。然而,这些名字仍将包含重音字符,如ç、ê和偶č和ć

不过,像“Micic”这样的简单搜索将无法与“Mičić”匹配——用户的期望是它会匹配

AJAX查找使用正则表达式来确定匹配项。我使用这个函数修改了正则表达式比较,试图匹配更多的重音字符。但是,它有点笨拙,因为它没有考虑所有角色

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;
}
函数makeComp(输入)
{
input=input.toLowerCase();
var输出=“”;
对于(变量i=0;i

除了这样的代换函数,还有更好的方法吗?也许要“取消”比较的字符串?

首先,我建议使用switch语句,而不是if-else-if的长字符串

那么,我不知道您为什么不喜欢当前的解决方案。它当然是最干净的。你不考虑“所有角色”是什么意思

除了使用第三方库之外,JavaScript中没有标准方法将重音字母映射为ASCII字母,因此您编写的方法与其他方法一样好

此外,我认为,“ß”对应的是“ss”,而不是一个“s”。注意土耳其语中带点和不带点的“i”——我相信它们指的是不同的字母。

我想不出更简单的“deaccent”方法,但您的替换可以简化一点:

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

}());

我制作了一个原型版本:

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];})
    );
};
使用类似于:

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

这会将字符串更改为a_o__u_o__ss

遇到这个旧线程,我想尝试一下快速函数。在调用函数replace()时,我依赖于管道分隔的OR设置变量的顺序。我的目标是尽可能多地使用标准的正则表达式实现javascript的replace()函数,这样繁重的处理就可以在低级浏览器优化的空间中进行,而不是在昂贵的javascript逐字符比较中进行

这一点都不科学,但当我将此线程中的其他功能插入到autocomplete中时,我的旧华为IDEOS android手机运行缓慢,而此功能可以自动完成:

function accentFold(inStr) {
  return inStr.replace(
    /([àáâãäå])|([çčć])|([èéêë])|([ìíîï])|([ñ])|([òóôõöø])|([ß])|([ùúûü])|([ÿ])|([æ])/g, 
    function (str, a, c, e, i, n, o, s, u, y, ae) {
      if (a) return 'a';
      if (c) return 'c';
      if (e) return 'e';
      if (i) return 'i';
      if (n) return 'n';
      if (o) return 'o';
      if (s) return 's';
      if (u) return 'u';
      if (y) return 'y';
      if (ae) return 'ae';
    }
  );
}
如果您是jQuery开发人员,这里有一个使用此函数的简便示例;您可以使用:icontains,方法与在选择器中使用:contains相同:

jQuery.expr[':'].icontains = function (obj, index, meta, stack) {
  return accentFold(
    (obj.textContent || obj.innerText || jQuery(obj).text() || '').toLowerCase()
  )
    .indexOf(accentFold(meta[3].toLowerCase())
  ) >= 0;
};
您还可以使用,它将自己描述为“轻量级模糊搜索库”。 零相关性”,用于模糊搜索。

有一种方法可以“取消”正在比较的字符串,而无需使用列出要删除的所有重音的替换函数

下面是我可以考虑从字符串中删除重音(和其他发音符号)的方法

在行动中看到它:

var string=“èaétéMičić.ÀÏÓÛ”;
console.log(字符串);
var string_norm=string.normalize('NFD')。替换(/[\u0300-\u036f]/g,”);
console.log(字符串_norm)我搜索并更新了答案,但一直在搜索,这是一个现代的解决方案,JavaScript(函数)的核心

但是,请注意,某些移动浏览器仍然缺少完全支持

在此之前,请密切关注所有平台和环境的全面支持

就这些吗? 不,我们现在可以进一步使用函数

var dotted = 'İstanbul';

console.log('EN-US: ' + dotted.toLocaleLowerCase('en-US'));
// expected output: "istanbul"

console.log('TR: ' + dotted.toLocaleLowerCase('tr'));
// expected output: "istanbul"

谢谢大家!

我认为这是最整洁的解决方案

var nIC = new Intl.Collator(undefined , {sensitivity: 'base'})
var cmp = nIC.compare.bind(nIC)
如果两个字符串相同,它将返回0,忽略重音

或者,您可以尝试
localecompare

'être'.localeCompare('etre',undefined,{sensitivity: 'base'})

我更喜欢一个
haystack.indexOfIgnoreAccents(needle)
选项:)我不喜欢做繁重的工作…这当然是我函数的一个更优雅的版本。感谢你的代码,我用你的函数替换了输入文本中的重音元音,效果很好。这是完美的-如此轻松地解决了我的用例,谢谢这是一个很好的解决方案。谢谢你,你帮我省下了好几个小时甚至好几天的痛苦。这无疑是一种很好的现代方式。请记住,没有IE或Safari<10的支持,因此您需要对其进行填充。它也不是一个微不足道的多边形填充(虽然不是巨大的),因此如果您有一个对大小敏感的构建,并且需要在旧浏览器上运行,那么它可能不是最好的选择。当然,这种担心每天都变得不那么重要了。“çî”。TolocalLowercase(‘en-US’)将返回“çî”,因此我的答案7岁时就非常有限了;这(大部分)是2020年实现这一目标的正确方式。我不相信(通过MDN的示例)需要绑定compare方法——它应该使用所需的上下文创建,因为
myNames.sort(nIC.compare)
工作得很好。
'être'.localeCompare('etre',undefined,{sensitivity: 'base'})