如何在JavaScript中查找一个字符串中所有出现的索引?

问题描述 投票:76回答:10

我试图在另一个字符串中找到所有出现的字符串的位置,不区分大小写。

例如,给定字符串:

I learned to play the Ukulele in Lebanon.

和搜索字符串le,我想获取数组:

[2, 25, 27, 33]

两个字符串都是变量 - 也就是说,我不能对它们的值进行硬编码。

我认为对于正则表达式来说这是一个简单的任务,但经过一段时间的努力找到一个可行的表达式之后,我没有运气。

我发现this example如何使用.indexOf()来实现这一点,但肯定有一个更简洁的方法来做到这一点?

javascript regex string indexof
10个回答
133
投票
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);
}

UPDATE

我没有在原始问题中发现搜索字符串需要是一个变量。我已经写了另一个版本来处理这个使用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>

-2
投票
function countInString(searchFor,searchIn){

 var results=0;
 var a=searchIn.indexOf(searchFor)

 while(a!=-1){
   searchIn=searchIn.slice(a*1+searchFor.length);
   results++;
   a=searchIn.indexOf(searchFor);
 }

return results;

}

15
投票

这是正则表达式免费版:

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;
}

12
投票

你确定可以做到这一点!

//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()中的结果对象,我的所有Javascript资源都掩盖了它的使用(除了给你匹配的字符串)。所以当他使用result.index时,那是某种未命名的匹配对象。在MDC description of exec中,他们实际上描述了这个对象。


2
投票

如果你只是想找到所有比赛的位置,我想指出你有点黑客:

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)

如果你有一个可变长度的RegEx,它可能不适用但对某些人来说可能会有所帮助。


1
投票

使用String.prototype.match

以下是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']

0
投票

按照@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;
}

0
投票

这是一个简单的代码

function getIndexOfSubStr(str, serchToken, preIndex, output){
		 var result = str.match(serchToken);
     if(result){
     output.push(result.index +preIndex);
     str=str.substring(result.index+serchToken.length);
     getIndexOfSubStr(str, serchToken, preIndex, output)
     }
     return output;
  };

var str = "my name is 'xyz' and my school name is 'xyz' and my area name is 'xyz' ";
var  serchToken ="my";
var preIndex = 0;

console.log(getIndexOfSubStr(str, serchToken, preIndex, []));

0
投票

感谢所有的答复。我仔细检查了所有这些,并提出了一个函数,它给出了第一个'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
}

-1
投票

以下代码将为您完成以下任务:

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")
© www.soinside.com 2019 - 2024. All rights reserved.