我有一个带有字符串属性的对象数组,我使用正则表达式搜索多个关键字。例如,如果集合看起来像这样
collection = [
{searchString: 'Troarn Lower Normandy France'},
{searchString: 'Tröbitz Brandenburg Germany'},
{searchString: 'Tröbnitz Thuringia Germany'},
{searchString: 'Tröchtelborn Thuringia Germany'},
{searchString: 'Trochtelfingen Baden-Württemberg Germany'},
{searchString: 'Trockenborn-Wolfersdorf Thuringia Germany'},
{searchString: 'Trodena Trentino-Alto Adige Italy'},
{searchString: 'Trodica The Marches Italy'},
{searchString: 'Trofaiach Styria Austria'},
{searchString: 'Trofarello Piedmont Italy'}
];
我有一个文本字符串可以像这样搜索
text = 'tro france';
我通过拆分文本来获取关键字
keywords = text.split(' ');
然后从这些关键字
构建一个正则表达式regex = '';
for (i = 0; i < keywords.length; i++ ) {
if (keywords[i] !== "" && keywords[i] !== undefined) {
regex += "(?=(^|.*\\s)" + keywords[i] + ")";
}
}
regex = new RegExp(regex, "i");
所以文字'tro france'
会给这个正则表达式/(?=(^|.*\s)tro)(?=(^|.*\s)france)/i
并将匹配集合中的第一个项目。
我会像这样搜索这个集合
for (i = 0; i < collection.length; i++) {
if (collection[i].searchString.search(regex) !== -1) {
// ... do stuff here
}
}
但现在我想强调搜索字符串中的关键字。 例如,如果文字是“法国”。我想要的话是&#39; tro&#39; 和法国&#39;在我显示结果的地方加下划线。我可以做这个 以一种简单的方式,但我不知道如何做多个匹配和 更换。我已经有一个,但只有我不做才有效 空格并跳转到其他关键字。
例如,如果文字很简单,那么&#34;非跳跃&#34;但像'Troarn Lo'
这样的直接比赛然后我可以像这样替换它
emphasized = new RegExp('('+text+'.*?)', 'i');
emphasized = collection[i]searchString.replace(emphasized, '<em>$1</em>');
但我在多个关键字部分完全空白。
所以,如果文本是'Tro Lo Nor Fra'
,我可以将集合中的第一项与正则表达式匹配,但在此之后,我想强调这些关键字,就像我上面所做的那样,除了所有关键字
我怎样才能做到这一点?
答案 0 :(得分:1)
您可以将所有关键字组合到一个正则表达式中。请注意,这将使g标志成为强制性的。
emphasized = new RegExp(keywords.join('|'), 'ig');
emphasized = collection[i].searchString.replace(emphasized, '<em>$&</em>');
请注意,这会突出显示每个每个关键字的出现次数。另外,请使用<mark>
代替<em>
。当与RegExp一起使用时,关键字应该被转义。
答案 1 :(得分:0)
以下答案取决于您/想要支持的浏览器。所有新的浏览器都支持它,但可能在旧的IE中给你带来问题(我没有找到确切的compat信息)。
您也可以使用String.prototype.indexOf
,而不是笨拙的正则表达式。 它的缺点是不具有初始字符串的保证顺序 *,但它具有以下优点:
您的修改示例:
keywords = text.split(' ');
for (var i = 0; i < collection.length; i++) {
for (var j = 0; j < keywords.length; j++) {
var position = collection[i].indexOf(keywords[j]);
if (position !== -1) {
/* keyword[j] has been found at [position], so you could do: */
// insert "<em>" markup into string at [position]
// increase the matchcounter by 1
}
}
}
// show results according to matchcounter, e.g. full match only
// (matchcounter === keywords.length)
编辑:*实际上,您可以使用第二个参数位置从上次点击的位置开始搜索。
答案 2 :(得分:0)
以下是我将这样做的方式:
var query = 'tro al it';
// first we extract the terms from the query and we normalize them:
var corr = {
'ae':'(?:ae|æ)', 'oe':'(?:oe|œ)',
'ss':'(?:ss|ß)', 'ß':'(?:ß|ss)',
'a':'[aàâä]', 'e':'[eéèêë]', 'i':'[iîï]', 'o':'[oôö]', 'u':'[uûü]',
'c':'[cç]', 'y':'[yÿ]' }; // need to be completed
var terms = query.toLowerCase()
.replace(/(?=[aeiyoucs])(?:[ao]e?|[eiuçy]|ss)/g, function (m) {
return corr[m];
}).split(/\s+/);
// now we build patterns to be able to filter or to find:
var testPatterns = terms.map(function (item) {
return new RegExp('(?:^|[- \'])' + item, 'i');
});
var HLPattern = new RegExp('(^|[- \'])(' + terms.join('|') + ')', 'ig');
// usage:
var results = collection;
// to filter the results:
testPatterns.forEach(function(pattern) {
results = results.filter(function (item) {
return pattern.test(item.searchString);
});
});
// to highlight the results:
results = results.map(function (item) {
item.searchString = item.searchString.replace(HLPattern, '$1<em>$2</em>');
return item;
});