我有一个纯字符串
"A <br> B <br/> C <br /> D <br/>"
以及一组可能的子字符串,如
['<br>','<br/>','<br />'];
在字符串中某个特定字符串的第n次出现的整个字符串中找到索引是微不足道的,所以我可以在第n个'<br>
'或第n个'<br/>
'的整个字符串上找到索引,但怎么可能找到这些字符串中任何一个的第n个出现呢?
例如,如果我需要2'出现,在这种情况下,它将在9'字符处,也就是说,将第一个<br>
计数为第一次出现,将第二个<br/>
计数为第二次出现
编辑:查找特定字符串第n次出现的索引可以像这样完成
var index = string.split('<br>', 2).join('<br>').length;
这样我就可以找到不同的事件。问题是要找到这些字符串中任何一个的出现。
您可以尝试使用这样的正则表达式:
let testString="A <br> B <br/> C <br /> D <br/>";
//Array of substrings to be searched for
let testItems=['<br>','<br/>','<br />'];
//Construction of the regular expression from the given array
let regex=new RegExp(testItems.join("|"),"g");
//Getting all matches for the provided regex and reducing it to an array of indices only
let indices=[...testString.matchAll(regex)].map(match=>match.index);
console.log(indices);
第n次出现可以很容易地从索引数组中恢复。如果您需要知道哪个子字符串也被命中,您也可以修改它。
更新
上面的答案没有考虑到搜索项包含正则表达式特殊字符的可能性。要处理这种情况,必须手动转义输入,如下所示。
let testString="A <br> B <br/> C <br /> D <br/> E <br $> F <br []/>";
//Array of substrings to be searched for
let testItems=['<br>','<br/>','<br />','<br $>','<br []/>'];
//Function to return an escaped version of the input string
let escapeRegex=(string)=> string.replace(/[-/\^$*+?.()|[]{}]/g, '\$&');
//Construction of the regular expression from the given array
let regex=new RegExp(testItems.map(item=>escapeRegex(item)).join("|"),"g");
//Getting all matches for the provided regex and reducing it to an array of indices only
let indices=[...testString.matchAll(regex)].map(match=>match.index);
console.log(indices);
转义输入的函数是从以下问题的答案中借用的:JavaScript中是否有RegExp.escape函数?
感谢@ScottSauyet和@Ivar对的反馈
递归解决方案在这里是有意义的,只要您不希望寻找第10000个匹配或类似的匹配。这里有一种方法:
const indexOfAny = (string, substrings, pos = 0) => {
const positions = substrings .map (ss => string .indexOf (ss, pos))
.filter (n => n > -1)
return positions .length == 0 ? -1 : Math .min (... positions)
}
const nthOfAny = (n, string, subtrings, pos = 0) => {
const first = indexOfAny (string, substrings, pos)
return n <= 1
? first
: first == -1
? -1
: nthOfAny (n - 1, string, substrings, 1 + indexOfAny (string, substrings, pos))
}
const string = 'A <br> B <br/> C <br /> D <br/>'
const substrings = ['<br>','<br/>','<br />']
console. log (
nthOfAny (2, string, substrings)
)
console.log (
[1, 2, 3, 4, 5, 6] .map (n => nthOfAny (n, string, substrings))
)
我们首先定义indexOfAny
,它接受一个字符串、一个要搜索的子字符串数组和(可选(一个初始位置,它返回第一个找到的位置,如果没有找到,则返回-1
。
然后,nthOfAny
取一个序数(1
表示第一个,2
表示第二个,等等(和与上面相同的自变量,并通过将pos
增加到先前找到的那个并减少n
来递归地找到那个,直到它碰到刚好返回indexOfAny
的结果的基本情况。
有相当多的额外复杂性意味着使用-1
来表示没有找到任何东西,以匹配indexOf
。对于这种情况,一个更简单的解决方案将返回Infinity
:
const indexOfAny = (string, substrings, pos = 0) =>
Math.min (
... substrings .map (ss => string .indexOf (ss, pos)) .filter (n => n > -1)
)
const nthOfAny = (n, string, subtrings, pos = 0) =>
n <= 1
? indexOfAny (string, substrings, pos)
: nthOfAny (n - 1, string, substrings, 1 + indexOfAny (string, substrings, pos))