我正在使用基于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;
}
除了这样的替代功能外,还有更好的方法吗?也许是为了“去除”被比较的字符串?
答案 0 :(得分:18)
这应该有所帮助:它被称为重音折叠:
http://alistapart.com/article/accent-folding-for-auto-complete
答案 1 :(得分:14)
有一种方法可以“对要比较的字符串进行消音” ,而无需使用替换功能,该功能列出要删除的所有重音...
这里是easiest solution,我可以考虑从字符串中删除重音符号(和其他变音符号)。
查看实际效果:
var string = "Ça été Mičić. ÀÉÏÓÛ";
console.log(string);
var string_norm = string.normalize('NFD').replace(/[\u0300-\u036f]/g, "");
console.log(string_norm);
希望有帮助。
答案 2 :(得分:12)
来到这个旧线程,并认为我会尝试快速执行功能。在函数replace()调用时,我依赖于管道分隔的OR设置变量的排序。我的目标是使用标准的正则表达式实现javascript的replace()函数尽可能多地使用,以便重处理可以在低级别的浏览器优化空间中进行,而不是在昂贵的javascript char-by-char比较中进行
它根本不科学,但是当我将此线程中的其他功能插入我的自动完成功能时,我的旧华为IDEOS安卓手机很慢,而这个功能拉链:
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与你使用的方式相同:在选择器中包含:
jQuery.expr[':'].icontains = function (obj, index, meta, stack) {
return accentFold(
(obj.textContent || obj.innerText || jQuery(obj).text() || '').toLowerCase()
)
.indexOf(accentFold(meta[3].toLowerCase())
) >= 0;
};
答案 3 :(得分:7)
我认为没有更容易的方式来“消除”,但你的替代可以更加简化:
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] + ']';
});
};
}());
答案 4 :(得分:3)
我搜索并提高了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"
谢谢!
答案 5 :(得分:0)
我制作了一个原型版本:
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();
这会将String更改为a_o_u_A_O_U_ss
答案 6 :(得分:0)
我认为这是最干净的解决方案
var nIC = new Intl.Collator(undefined , {sensitivity: 'base'})
var cmp = nIC.compare.bind(nIC)
如果两个字符串相同(忽略重音符号),它将返回0。
或者,您尝试localecompare
'être'.localeCompare('etre',undefined,{sensitivity: 'base'})
答案 7 :(得分:-1)
首先,我建议使用switch语句而不是长字符串if-else if ...
然后,我不确定你为什么不喜欢你当前的解决方案。它当然是最干净的。不考虑“所有人物”是什么意思?
JavaScript中没有标准方法可以使用第三方库将重音字母映射到ASCII字母,因此您编写的字符与任何字母一样好。
另外,“ß”我相信映射到“ss”,而不是单个“s”。并且要小心土耳其语中带有和不带点的“我” - 我相信它们指的是不同的字母。
答案 8 :(得分:-1)
您还可以使用http://fusejs.io进行模糊搜索。