第一件事:
- 我不验证输入。这个答案为您提供了一种方法。您应该验证输入,特别是因为您说它来自用户:)
- 我们将使用来自this blog 的
matchRecursive 函数。
这个函数将帮助我们对正确的括号进行分组。
var matchRecursive = function () {
var formatParts = /^([\S\s]+?)\.\.\.([\S\s]+)/,
metaChar = /[-[\]{}()*+?.\\^$|,]/g,
escape = function (str) {
return str.replace(metaChar, "\\$&");
};
return function (str, format) {
var p = formatParts.exec(format);
if (!p) throw new Error("format must include start and end tokens separated by '...'");
if (p[1] == p[2]) throw new Error("start and end format tokens cannot be identical");
var opener = p[1],
closer = p[2],
/* Use an optimized regex when opener and closer are one character each */
iterator = new RegExp(format.length == 5 ? "["+escape(opener+closer)+"]" : escape(opener)+"|"+escape(closer), "g"),
results = [],
openTokens, matchStartIndex, match;
do {
openTokens = 0;
while (match = iterator.exec(str)) {
if (match[0] == opener) {
if (!openTokens)
matchStartIndex = iterator.lastIndex;
openTokens++;
} else if (openTokens) {
openTokens--;
if (!openTokens)
results.push(str.slice(matchStartIndex, match.index));
}
}
} while (openTokens && (iterator.lastIndex = matchStartIndex));
return results;
};
}();
接下来,这是我将根据您提供的数据使用的算法:
- 我们通过简单地检查
str.startsWith("(") 来确定我们是第一种输入还是第二种输入;
-
我们初始化以下内容:
-
groupedItems 用于将第二类输入转换为第一类输入的数组,以便我们之后对两者使用相同的代码
-
returnArr 返回数据
我们遍历groupedItems并准备一个空的keywordObj
- 在这个循环中,我们通过使用
matchRecursive 函数并在' OR ' 之后拆分结果来确定哪些是any 关键字 - 结果项目将是any 项目
- 对于其余的关键字(
all 或 not),我们需要得到一个单词 - 所以我们再次拆分,这次是在 " " 之后,拆分的结果是一个关键字数组
- 我们遍历关键字并通过检查它们是否以
- 开头来确定它们是否为not 关键字,否则我们将它们视为all 关键字。
这是它的代码:
function output(str){
var groupedItems = [];
if(str.startsWith("(")){
groupedItems = matchRecursive(str,"(...)");
} else {
groupedItems.push(str);
}
var returnArr = [];
for (var i = 0; i<groupedItems.length;i++){
var keywordObj = {all:[], any:[], not: []};
var thisGroup = groupedItems[i];
var arr = matchRecursive(thisGroup, "(...)");
if (arr.length != 1) throw new Error("unexpected input");
keywordObj.any = arr[0].split(" OR ");
var restOfKeywords = thisGroup.split(" (" + arr[0] + ") ");
for (var j = 0; j<restOfKeywords.length; j++){
var keyWords = restOfKeywords[j].split(" ");
for (var k = 0; k<keyWords.length;k++){
if (keyWords[k].startsWith("-"))
keywordObj.not.push(keyWords[k])
else
keywordObj.all.push(keyWords[k])
}
}
returnArr.push(keywordObj);
}
return returnArr;
}
// input "(Keyword1 Keyword2 (Keyword3 OR Keyword4) -Keyword5 -Keyword6) OR (Keyword7 Keyword8 (Keyword9 OR Keyword10) -Keyword11 -Keyword12)"
// output [{"all":["Keyword1","Keyword2"],"any":["Keyword3","Keyword4"],"not":["-Keyword5","-Keyword6"]},{"all":["Keyword7","Keyword8"],"any":["Keyword9","Keyword10"],"not":["-Keyword11","-Keyword12"]}]