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

rlcwz9us  于 2023-03-16  发布在  Java
关注(0)|答案(8)|浏览(167)

我使用基于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;
}

除了像这样的替换函数之外,还有更好的方法吗?也许是对被比较的字符串进行“去重音”?

beq87vna

beq87vna1#

有一种方法可以“*“去掉”正在比较的字符串的重音 *”,而不使用列出所有要删除的重音的替换函数...
下面是我可以考虑的easiest solution,它可以从字符串中删除重音符号(和其他发音符号)。
查看实际应用:

var string = 'Ça été Mičić. ÀÉÏÓÛ';
console.log(string);

var string_norm = string.normalize('NFD').replace(/\p{Diacritic}/gu, ''); // Old method: .replace(/[\u0300-\u036f]/g, "");
console.log(string_norm);
  • .normalize(…)分解字母和发音符号。
  • .replace(…)将删除所有发音符号。
zzlelutf

zzlelutf2#

我遇到了这个老线程,我想我应该尝试一下做一个快速的函数。当变量在函数replace中匹配时,我依赖于管道分隔的OR设置变量的顺序我的目标是使用标准的正则表达式实现javascript的replace()函数尽可能多地使用,以便在低级浏览器优化空间中进行繁重处理,而不是昂贵的JavaScript字符对字符的比较。
这一点也不科学,但当我把这个线程中的其他函数插入自动完成时,我的旧华为IDEOS安卓手机React迟钝,而这个函数却在沿着:

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开发人员,这里有一个使用此函数的简便示例;你可以像在选择器中使用:contains一样使用:icontains:

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

czfnxgou3#

我搜索并投票支持herostwist的答案,但继续搜索,真的,这里有一个现代的解决方案,JavaScript的核心(string.localeCompare函数)

var a = 'réservé'; // with accents, lowercase
var b = 'RESERVE'; // no accents, uppercase

console.log(a.localeCompare(b));
// expected output: 1
console.log(a.localeCompare(b, 'en', {sensitivity: 'base'}));
// expected output: 0
  • 但是请注意,某些移动的浏览器仍然缺少完全支持!!!*

在此之前,请继续关注所有平台和环境的全面支持。
∮仅此而已?∮
不,我们现在可以更进一步,使用string.toLocaleLowerCase函数。

var dotted = 'İstanbul';

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

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

谢谢你!

gg0vcinb

gg0vcinb4#

我想不出更简单的“去重音”的方法,但是你的替换可以更精简一点:

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

}());
8wtpewkr

8wtpewkr5#

我觉得这是最好的解决办法

var nIC = new Intl.Collator(undefined , {sensitivity: 'base'})
var cmp = nIC.compare.bind(nIC)

如果两个字符串相同,则返回0,忽略重音。
或者您可以尝试localecompare

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

ej83mcc06#

我做了一个原型:

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_A_O_U_ss

mqxuamgl

mqxuamgl7#

您还可以使用http://fusejs.io进行模糊搜索,它将自己描述为“轻量级模糊搜索库。零依赖项”。

hmmo2u0o

hmmo2u0o8#

首先,我建议使用switch语句代替一长串if-else if...
那么,我不知道你为什么不喜欢你现在的解决方案。它肯定是最干净的一个。你说不考虑“所有字符”是什么意思?
除了使用第三方库之外,JavaScript中没有标准方法可以将重音字母Map为ASCII字母,因此您编写的这个函数与其他函数一样好。
还有,“ß”我相信Map到“ss”,而不是一个单一的“s”。而且要小心土耳其语中有点和没有点的“i”--我相信它们指的是不同的字母。

相关问题