Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/regex/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 使用regExp将字符串中的多个单词动态匹配到另一个单词_Javascript_Regex - Fatal编程技术网

Javascript 使用regExp将字符串中的多个单词动态匹配到另一个单词

Javascript 使用regExp将字符串中的多个单词动态匹配到另一个单词,javascript,regex,Javascript,Regex,我们都知道,regExp可以使用两个字符串中的一个公共字作为匹配的标准来匹配两个字符串。此代码将“我喜欢苹果”与“苹果”匹配,因为它们都有相同的“苹果” var str1 = "apples"; var test1 = "I like apples"; var reg1 = new RegExp(str1, "i"); if (test1.match(reg1)) { console.log(str1 + " is matched"); } 但是,如果我不需要使用单个公共词(或字符串

我们都知道,regExp可以使用两个字符串中的一个公共字作为匹配的标准来匹配两个字符串。此代码将“我喜欢苹果”与“苹果”匹配,因为它们都有相同的“苹果”

var str1 = "apples";
var test1 = "I like apples";
var reg1 = new RegExp(str1, "i");

if (test1.match(reg1)) {
    console.log(str1 + " is matched");
}
但是,如果我不需要使用单个公共词(或字符串的公共部分)来匹配字符串,而是需要使用多个公共词来匹配两个字符串,这些公共词可能会被其他词分隔开,那该怎么办?让我给你举个例子:

test2
=“我喜欢多汁的红色水果”应该与
str2
=“多汁的水果”匹配,因为
test2
包含所有
str2
第二个关键字(请参见下面的对象),尽管它之间有其他关键字

棘手的是,我不能确切地知道字符串是什么,所以我必须动态地匹配它们。我不知道的字符串是用户输入字段的值,有很多可能。此值将与存储在此对象中的字符串匹配:

var str2 = {
    "red apples": "fruits",
    "juicy fruits": "price : $10"
};
因此,无论用户在输入字段中键入什么,它必须是匹配的当且仅当它包含一个对象属性的所有单词时。因此,在本例中,“多汁红色和成熟的水果”应与第二个对象属性匹配,因为它包含其所有关键字

编辑:我的目标是输出与我匹配的字符串关联的值。在我的示例中,如果匹配了第一个键,则应该输出'fruits'。如果“多汁水果”是匹配的,它应该输出“价格:$10”。获取与对象键关联的字符串是用户必须使用输入搜索它们的原因

是否可以使用纯javascript对regExp执行此操作


以下是我(拙劣地)尝试做的:

对于您描述的情况,您甚至不需要正则表达式。如果在空格上拆分搜索字符串;您可以检查要匹配的每个单词是否包含在搜索单词数组中

function matchesAllWords(searchWords, inputString) {
  var wordsToMatch = inputString.toLowerCase().split(' ');

  return wordsToMatch.every(
    word => searchWords.indexOf(word) >= 0);
}
在下面的代码段中,键入
输入
会导致重新计算
搜索词
。然后为匹配的
li
元素指定
.match
类以突出显示它们

函数更新类(e){
var searchWords=e.target.value.toLowerCase().split(“”);
forEach(listItem=>listItem.classList.remove('match');
listItems.filter(
listItem=>
匹配所有单词(搜索词,listItem.innerText))
弗雷奇先生(
matchingListItem=>
matchingListItem.classList.add('match');
}
函数匹配所有单词(搜索词、输入字符串){
var WordToMatch=inputString.toLowerCase().split(“”);
每一天返回一次(
word=>searchWords.indexOf(word)>=0);
}
函数搜索属性(e){
var searchWords=e.target.value.toLowerCase().split(“”);
for(propertiesToSearch中的var属性){
if(匹配所有词(搜索词、属性)){
log(property,propertiesToSearch[property]);
}
}
}
var propertiesToSearch={
“红苹果”:1,
“多汁水果”:2
};
listItems=[].slice.call(
document.getElementById('matches').querySelectorAll('li'))
);
document.getElementById('search')。addEventListener('keyup',updateClass);
document.getElementById('search')。addEventListener('keyup',searchProperties)
.match{
颜色:绿色;
}

搜索:
  • 红苹果
  • 多汁水果

我认为将数据结构从对象文字转换为数组可能会使您受益,如下所示:

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(..)
的实现:


希望这有帮助

为每个要检查的单词建立一个lookahead列表,比如
(?=.*\b UICY\b)(?=.*\b水果\b)
str2
是一个以
红苹果
多汁水果
为键的对象
test2
只有
“多汁”、“红色”和“苹果”
。我不理解这样的说法,“
test2
包含所有的
str2
单词……”。我误解了什么?@wcarroll:我的句子用错了词:我想说
test2
包含了所有
str2
第二个关键字。我编辑了我的帖子,谢谢你指出。@Hal_9100将字符串化的数字作为
str2
对象中的值是怎么处理的?那部分我还不清楚。这个数据结构真的有必要吗?谢谢,你的答案很好。问题是我需要获取与我匹配的字符串相关联的字符串/值(在我的演示中由数字表示)。这就是为什么用户必须首先搜索它们。我试图调整您的解决方案,使其能够使用对象中的键而不是DOM元素中的文本,但我无法使其工作。我并不是试图搜索DOM,而是搜索对象的键,以便在匹配完成后获得它们的值。用你的方法有没有办法做到这一点?再次感谢您在回答中投入的时间和精力。您可以使用
for…in
循环浏览属性,检查输入的
是否与属性名称中的所有单词匹配,如果匹配,则输出相应的值(
str2[key]
或其他任何内容)@Hal_9100请参见更新–正如qxz建议的那样,可以使用
匹配所有单词
来使用
搜索关键字
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);
}