Answers:
var str = "I learned to play the Ukulele in Lebanon."
var regex = /le/gi, result, indices = [];
while ( (result = regex.exec(str)) ) {
indices.push(result.index);
}
更新
我未能在原始问题中发现搜索字符串需要是一个变量。我写了另一个版本来处理使用的这种情况indexOf
,所以您回到了开始的地方。正如Wrikken在评论中所指出的那样,要对带有正则表达式的一般情况执行此操作,您需要转义特殊的正则表达式字符,这时我认为正则表达式解决方案变得比其价值更令人头疼。
function getIndicesOf(searchStr, str, caseSensitive) {
var searchStrLen = searchStr.length;
if (searchStrLen == 0) {
return [];
}
var startIndex = 0, index, indices = [];
if (!caseSensitive) {
str = str.toLowerCase();
searchStr = searchStr.toLowerCase();
}
while ((index = str.indexOf(searchStr, startIndex)) > -1) {
indices.push(index);
startIndex = index + searchStrLen;
}
return indices;
}
var indices = getIndicesOf("le", "I learned to play the Ukulele in Lebanon.");
document.getElementById("output").innerHTML = indices + "";
<div id="output"></div>
new RegExp(searchStr)
就是这样,是的,在一般情况下,您必须转义特殊字符。除非您需要这种一般性,否则这确实不值得做。
searchStr=aaa
那个str=aaaaaa
。然后,您将不会发现4个事件,而只会发现2个,因为您正在searchStr.length
循环中进行跳过。
这是正则表达式的免费版本:
function indexes(source, find) {
if (!source) {
return [];
}
// if find is empty string return all indexes.
if (!find) {
// or shorter arrow function:
// return source.split('').map((_,i) => i);
return source.split('').map(function(_, i) { return i; });
}
var result = [];
for (i = 0; i < source.length; ++i) {
// If you want to search case insensitive use
// if (source.substring(i, i + find.length).toLowerCase() == find) {
if (source.substring(i, i + find.length) == find) {
result.push(i);
}
}
return result;
}
indexes("I learned to play the Ukulele in Lebanon.", "le")
编辑:如果您想匹配'aaaa'和'aa'之类的字符串来查找[0,2],请使用以下版本:
function indexes(source, find) {
if (!source) {
return [];
}
if (!find) {
return source.split('').map(function(_, i) { return i; });
}
var result = [];
var i = 0;
while(i < source.length) {
if (source.substring(i, i + find.length) == find) {
result.push(i);
i += find.length;
} else {
i++;
}
}
return result;
}
var result = indexes('aaaa', 'aa')
怎么办?预期结果应为[0, 1, 2]
或[0, 2]
?
i+=find.length;
和i++
您确定可以做到!
//make a regular expression out of your needle
var needle = 'le'
var re = new RegExp(needle,'gi');
var haystack = 'I learned to play the Ukulele';
var results = new Array();//this is the results you want
while (re.exec(haystack)){
results.push(re.lastIndex);
}
编辑:学习拼写RegExp
此外,我意识到这不是正是你想要什么,lastIndex
告诉我们针不是开始的结束,但它很接近-你可以推re.lastIndex-needle.length
到结果数组...
编辑:添加链接
@Tim Down的答案使用了RegExp.exec()中的result对象,我所有的Javascript资源都掩盖了它的使用(除了为您提供匹配的字符串之外)。因此,当他使用时result.index
,这就是某种未命名的匹配对象。在exec的MDC描述中,他们实际上详细描述了该对象。
一个班轮使用String.protype.matchAll
(ES2020):
[...sourceStr.matchAll(new RegExp(searchStr, 'gi'))].map(a => a.index)
使用您的值:
const sourceStr = 'I learned to play the Ukulele in Lebanon.';
const searchStr = 'le';
const indexes = [...sourceStr.matchAll(new RegExp(searchStr, 'gi'))].map(a => a.index);
console.log(indexes); // [2, 25, 27, 33]
如果您担心要map()
在一个行中进行价差和a for...of
运算,那么我会循环运行一百万次迭代(使用您的字符串)。一支班轮平均1420毫秒,而for...of
在我的机器上平均1150毫秒。这并不是一个微不足道的区别,但是如果您只进行少量比赛,一支衬板就可以正常工作。
如果您只想查找所有比赛的位置,我想向您指出一点技巧:
var haystack = 'I learned to play the Ukulele in Lebanon.',
needle = 'le',
splitOnFound = haystack.split(needle).map(function (culm)
{
return this.pos += culm.length + needle.length
}, {pos: -needle.length}).slice(0, -1); // {pos: ...} – Object wich is used as this
console.log(splitOnFound);
如果RegExp的长度可变,则可能不适用,但对于某些情况可能会有所帮助。
这是区分大小写的。对于不区分大小写的用户,String.toLowerCase
请先使用功能。
这是一个简单的代码
function getIndexOfSubStr(str, searchToken, preIndex, output){
var result = str.match(searchToken);
if(result){
output.push(result.index +preIndex);
str=str.substring(result.index+searchToken.length);
getIndexOfSubStr(str, searchToken, preIndex, output)
}
return output;
};
var str = "my name is 'xyz' and my school name is 'xyz' and my area name is 'xyz' ";
var searchToken ="my";
var preIndex = 0;
console.log(getIndexOfSubStr(str, searchToken, preIndex, []));
遵循@jcubic的答案,他的解决方案引起了我的情况的混乱。
例如var result = indexes('aaaa', 'aa')
,它将返回[0, 1, 2]
而不是,[0, 2]
因此我如下更新了他的解决方案以匹配我的情况
function indexes(text, subText, caseSensitive) {
var _source = text;
var _find = subText;
if (caseSensitive != true) {
_source = _source.toLowerCase();
_find = _find.toLowerCase();
}
var result = [];
for (var i = 0; i < _source.length;) {
if (_source.substring(i, i + _find.length) == _find) {
result.push(i);
i += _find.length; // found a subText, skip to next position
} else {
i += 1;
}
}
return result;
}
感谢所有的答复。我仔细研究了所有这些内容,并想出了一个函数,该函数为“ needle”子字符串的每次出现提供第一个最后一个索引。我将其张贴在这里,以防它对某人有所帮助。
请注意,仅在每次出现时才与原始请求不同。因为您不需要保持针的长度,所以它更适合我的用例。
function findRegexIndices(text, needle, caseSensitive){
var needleLen = needle.length,
reg = new RegExp(needle, caseSensitive ? 'gi' : 'g'),
indices = [],
result;
while ( (result = reg.exec(text)) ) {
indices.push([result.index, result.index + needleLen]);
}
return indices
}
检查此解决方案,它也可以找到相同的字符串,让我知道是否缺少某些内容。
function indexes(source, find) {
if (!source) {
return [];
}
if (!find) {
return source.split('').map(function(_, i) { return i; });
}
source = source.toLowerCase();
find = find.toLowerCase();
var result = [];
var i = 0;
while(i < source.length) {
if (source.substring(i, i + find.length) == find)
result.push(i++);
else
i++
}
return result;
}
console.log(indexes('aaaaaaaa', 'aaaaaa'))
console.log(indexes('aeeaaaaadjfhfnaaaaadjddjaa', 'aaaa'))
console.log(indexes('wordgoodwordgoodgoodbestword', 'wordgood'))
console.log(indexes('I learned to play the Ukulele in Lebanon.', 'le'))
下面的代码将为您完成这项工作:
function indexes(source, find) {
var result = [];
for(i=0;i<str.length; ++i) {
// If you want to search case insensitive use
// if (source.substring(i, i + find.length).toLowerCase() == find) {
if (source.substring(i, i + find.length) == find) {
result.push(i);
}
}
return result;
}
indexes("hello, how are you", "ar")
这是来自MDN文档本身的示例:
var str = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
var regexp = /[A-E]/gi;
var matches_array = str.match(regexp);
console.log(matches_array);
// ['A', 'B', 'C', 'D', 'E', 'a', 'b', 'c', 'd', 'e']
le
这里的可变字符串如何?即使new Regexp(str);
潜伏在使用特殊字符的危险中,也要进行搜索$2.50
。有点像regex = new Regexp(dynamicstring.replace(/([\\.+*?\\[^\\]$(){}=!<>|:])/g, '\\$1'));
恕我直言。我不确定js是否具有内置的正则表达式转义机制。