我们都知道regExp可以使用两个字符串中的公共字匹配两个字符串作为匹配的标准。此代码将匹配&#34;我喜欢苹果&#34; 到&#34; 苹果&#34; < / em>因为他们都有&#34;苹果&#34;共同的。
var str1 = "apples";
var test1 = "I like apples";
var reg1 = new RegExp(str1, "i");
if (test1.match(reg1)) {
console.log(str1 + " is matched");
}
但是如果不使用单个公共字(或字符串的公共部分)匹配字符串,我需要使用多个常用字匹配两个字符串,这些字可能被其他字分开?让我举个例子:
test2
= &#34;我喜欢多汁红色水果&#34; 应该匹配str2
= &#34; 多汁的水果&#34; 因为test2
包含所有str2
个第二关键词(参见下面的对象),即使它之间有其他的话。
棘手的部分是,我无法知道字符串是什么,所以我必须动态匹配它们。我不知道的字符串是用户输入字段的值,并且有许多可能性。此值将与存储在此对象中的字符串匹配:
var str2 = {
"red apples": "fruits",
"juicy fruits": "price : $10"
};
因此无论输入字段中的用户类型如何,当且仅当它包含其中一个对象属性的所有单词时,它必须是匹配的。因此,在此示例中,&#34; 多汁 红色和成熟水果 &#34;应匹配第二个对象属性,因为它包含所有关键字。
编辑:我的目标是输出与我匹配的字符串相关联的值。在我的例子中,如果第一个键匹配,那么&#39; fruits&#39;应该输出。如果多汁的水果&#39;匹配,它应该输出价格:10美元&#39;。获取与对象键关联的字符串是用户必须使用输入搜索它们的原因。
使用纯JavaScript可以使用regExp执行此操作吗?
这是我(很差)试图做的事情:https://jsfiddle.net/Hal_9100/fzhr0t9q/1/
答案 0 :(得分:1)
对于您所描述的情况,您甚至不需要正则表达式。如果在空格上拆分搜索字符串;你可以检查每个要匹配的单词是否包含在搜索词数组中。
function matchesAllWords(searchWords, inputString) {
var wordsToMatch = inputString.toLowerCase().split(' ');
return wordsToMatch.every(
word => searchWords.indexOf(word) >= 0);
}
在下面的代码段中,输入input
会导致重新计算searchWords
。然后,匹配的li
元素将被赋予.match
类以突出显示它们。
function updateClasses(e) {
var searchWords = e.target.value.toLowerCase().split(' ');
listItems.forEach(listItem => listItem.classList.remove('match'));
listItems.filter(
listItem =>
matchesAllWords(searchWords, listItem.innerText))
.forEach(
matchingListItem =>
matchingListItem.classList.add('match'));
}
function matchesAllWords(searchWords, inputString) {
var wordsToMatch = inputString.toLowerCase().split(' ');
return wordsToMatch.every(
word => searchWords.indexOf(word) >= 0);
}
function searchProperties(e) {
var searchWords = e.target.value.toLowerCase().split(' ');
for (var property in propertiesToSearch) {
if (matchesAllWords(searchWords, property)) {
console.log(property, propertiesToSearch[property]);
}
}
}
var propertiesToSearch = {
"red apples": 1,
"juicy fruit": 2
};
listItems = [].slice.call(
document.getElementById('matches').querySelectorAll('li')
);
document.getElementById('search').addEventListener('keyup', updateClasses);
document.getElementById('search').addEventListener('keyup', searchProperties);
.match {
color: green;
}
<label for="search">
Search:
</label>
<input type="text" name="search" id="search" />
<ul id="matches">
<li>red apples</li>
<li>juicy fruits</li>
</ul>
更新 要使用此类实现来搜索属性,请使用如下所示的for .. in
循环。再次,请参阅上下文中的代码片段。
function searchProperties(e) {
var searchWords = e.target.value.toLowerCase().split(' ');
for (var property in propertiesToSearch) {
if (matchesAllWords(searchWords, property)) {
console.log(property, propertiesToSearch[property]);
}
}
}
var propertiesToSearch = {
"red apples": 1,
"juicy fruit": 2
};
答案 1 :(得分:0)
我认为您可能会将数据结构从对象文字转换为如下所示的数组:
const wordGroupings = [
'red apples',
'juicy fruits'
];
我编写了一个processString
函数,它接受一个字符串和一些单词分组作为输入,并返回一个过滤的单词分组列表,其中单词分组中的每个单词都出现在输入字符串中。
换句话说,让我们想象测试字符串是:
const testString = 'I like big, frozen whales.';
让我们进一步想象你的wordGroupings
数组看起来像这样:
const wordGroupings = [
'whales frozen',
'big frozen whales toucan',
'big frozen',
'sweaty dance club',
'frozen whales big'
]
调用processString(wordGroupings, testString)
的输出将是:
[
'whales frozen',
'big frozen',
'frozen whales big'
]
如果这是您正在寻找的内容,请执行以下processString(..)
:
function processString(wordGroupings, testString) {
var regexes = wordGroupings.map(words => ({
origString: words,
regex: new RegExp(words.replace(/\s+/g, '|'), 'g'),
expCount: words.split(/\s+/g).length
})
);
filtered = regexes.filter(({regex, expCount}) =>
(testString.match(regex) || []).length === expCount
);
return filtered.map(dataObj => dataObj.origString);
}
希望这有帮助!