如何在 JavaScript 中查找一个字符串在另一个字符串中所有出现的索引?
我试图找到一个字符串在另一个字符串中所有出现的位置,不区分大小写。
例如,给定字符串:
I learned to play the Ukulele in Lebanon.
和搜索字符串le
,我想获取数组:
[2, 25, 27, 33]
两个字符串都是变量 - 即,我无法对它们的值进行硬编码。
我认为这对于正则表达式来说是一项简单的任务,但是在努力寻找一个可行的方法之后,我没有运气。
我找到了 这个示例,说明如何使用 完成此操作.indexOf()
,但肯定有一个更简洁的方法来做到这一点吗?
I'm trying to find the positions of all occurrences of a string in another string, case-insensitive.
For example, given the string:
I learned to play the Ukulele in Lebanon.
and the search string le
, I want to obtain the array:
[2, 25, 27, 33]
Both strings will be variables - i.e., I can't hard-code their values.
I figured that this was an easy task for regular expressions, but after struggling for a while to find one that would work, I've had no luck.
I found this example of how to accomplish this using .indexOf()
, but surely there has to be a more concise way to do it?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(20)
更新
我未能在原始问题中发现搜索字符串需要是一个变量。我编写了另一个版本来处理使用
indexOf
的情况,因此您回到了开始的地方。正如 Wrikken 在评论中指出的那样,要在正则表达式的一般情况下执行此操作,您需要转义特殊的正则表达式字符,此时我认为正则表达式解决方案变得比其价值更令人头痛。UPDATE
I failed to spot in the original question that the search string needs to be a variable. I've written another version to deal with this case that uses
indexOf
, so you're back to where you started. As pointed out by Wrikken in the comments, to do this for the general case with regular expressions you would need to escape special regex characters, at which point I think the regex solution becomes more of a headache than it's worth.使用
String.prototype.matchAll 的一个衬垫
(ES2020):使用你的值:
如果你担心在一行中进行展开和
map()
,我用for 运行它...of
循环一百万次迭代(使用您的字符串)。在我的机器上,一个衬垫平均为 1420 毫秒,而for...of
平均为 1150 毫秒。这并不是一个微不足道的差异,但如果您只进行少量比赛,那么单衬管就可以很好地工作。查看 caniuse 上的
matchAll
One liner using
String.prototype.matchAll
(ES2020):Using your values:
If you're worried about doing a spread and a
map()
in one line, I ran it with afor...of
loop for a million iterations (using your strings). The one liner averages 1420ms while thefor...of
averages 1150ms on my machine. That's not an insignificant difference, but the one liner will work fine if you're only doing a handful of matches.See
matchAll
on caniuse你一定可以做到这一点!
编辑:学习拼写 RegExp
另外,我意识到这并不完全是您想要的,因为
lastIndex
告诉我们针的末端不是开头,但已经很接近了 - 您可以将re.lastIndex-needle.length
推入结果数组中...编辑:添加链接
@Tim Down 的答案使用结果对象来自 RegExp.exec(),我所有的 Javascript 资源都掩盖了它的使用(除了给你匹配的字符串)。因此,当他使用
result.index
时,这是某种未命名的匹配对象。在 exec 的 MDC 描述中,他们实际上在不错的细节。You sure can do this!
Edit: learn to spell RegExp
Also, I realized this isn't exactly what you want, as
lastIndex
tells us the end of the needle not the beginning, but it's close - you could pushre.lastIndex-needle.length
into the results array...Edit: adding link
@Tim Down's answer uses the results object from RegExp.exec(), and all my Javascript resources gloss over its use (apart from giving you the matched string). So when he uses
result.index
, that's some sort of unnamed Match Object. In the MDC description of exec, they actually describe this object in decent detail.这是正则表达式免费版本:
编辑:如果您想匹配“aaaa”和“aa”等字符串来查找 [0, 2],请使用此版本:
Here is regex free version:
EDIT: and if you want to match strings like 'aaaa' and 'aa' to find [0, 2] use this version:
我参加聚会有点晚了(差不多 10 年零 2 个月),但未来的程序员的一种方法是使用 while 循环和
indexOf()
I am a bit late to the party (by almost 10 years, 2 months), but one way for future coders is to do it using while loop and
indexOf()
如果你只是想找到所有比赛的位置,我想告诉你一个小窍门:
如果您有可变长度的正则表达式,它可能不适用,但对于某些人来说可能会有所帮助。
这是区分大小写的。对于不区分大小写的情况,请先使用 String.toLowerCase 函数。
If you just want to find the position of all matches I'd like to point you to a little hack:
It might not be applikable if you have a RegExp with variable length but for some it might be helpful.
This is case sensitive. For case insensitivity use
String.toLowerCase
function before.我会推荐蒂姆的答案。但是,@blazs 的此评论指出“假设
searchStr=aaa
和str=aaaaaa
,那么您的代码将只找到 2 次,而不是找到 4 次。你在循环中通过 searchStr.length 进行跳过。”,通过查看 Tim 的代码,这是正确的,特别是这里的这一行:startIndex = index + searchStrLen;
Tim 的代码将无法找到正在搜索的字符串的实例,其长度在其自身范围内。所以,我修改了蒂姆的答案:如果我有一个
aaaaaa
的 str 和一个aaa
的 searchStr。PS 如果有人想在代码中添加注释来解释代码的工作原理,请说出来,我很乐意回复该请求。
I would recommend Tim's answer. However, this comment by @blazs states "Suppose
searchStr=aaa
and thatstr=aaaaaa
. Then instead of finding 4 occurences your code will find only 2 because you're making skips by searchStr.length in the loop.", which is true by looking at Tim's code, specifically this line here:startIndex = index + searchStrLen;
Tim's code would not be able to find an instance of the string that's being searched that is within the length of itself. So, I've modified Tim's answer:Changing it to
+ 1
instead of+ searchStrLen
will allow the index 1 to be in the indices array if I have an str ofaaaaaa
and a searchStr ofaaa
.P.S. If anyone would like comments in the code to explain how the code works, please say so, and I'll be happy to respond to the request.
感谢您的所有回复。我遍历了所有这些,并提出了一个函数,该函数给出了每次出现 'needle' 子字符串的第一个和最后一个索引。我将其发布在这里,以防它对某人有所帮助。
请注意,它与仅每次出现的开头的原始请求不同。它更适合我的用例,因为您不需要保持针的长度。
Thanks for all the replies. I went through all of them and came up with a function that gives the first an last index of each occurrence of the 'needle' substring . I am posting it here in case it will help someone.
Please note, it is not the same as the original request for only the beginning of each occurrence. It suits my usecase better because you don't need to keep the needle length.
这是一个简单的代码片段:
Here is a simple code snippet:
这就是我通常用来根据字符串位置获取字符串索引的方法。
我传递以下参数:
search:搜索位置的字符串
find:查找 位置的字符串
(默认为“全部”):查找字符串在搜索字符串中出现的位置
(如果为“all”,则返回完整的索引数组)
(如果为“last”,则返回最后一个位置)
This is what I usually use to get a string index also according to its position.
I pass following parameters:
search: the string where to search for
find: the string to find
position ('all' by default): the position by which the find string appears in search string
(if 'all' it returns the complete array of indexes)
(if 'last' it returns the last position)
嗨朋友们,这只是使用reduce和辅助方法查找匹配短语索引的另一种方法。当然 RegExp 更方便,也许内部是这样实现的。我希望你觉得它有用。
Hi friends this is just another way of finding indexes of matching phrase using reduce and a helper method. Of course RegExp is more convenient and perhaps is internally implemented somehow like this. I hope you find it useful.
检查这个解决方案,它也能够找到相同的字符串,如果缺少或不正确,请告诉我。
Check this solution which will able to find same character string too, let me know if something missing or not right.
按照@jcubic的回答,他的解决方案对我的案例造成了一些混乱
例如
var result =indexes('aaaa', 'aa')
将返回[0, 1, 2]
而不是[0, 2]
代码>所以我更新了他的解决方案如下以匹配我的情况
Follow the answer of @jcubic, his solution caused a small confusion for my case
For example
var result = indexes('aaaa', 'aa')
will return[0, 1, 2]
instead of[0, 2]
So I updated a bit his solution as below to match my case
这是我的代码(使用搜索和切片方法)
Here's my code (using search and slice methods)
如果您无论如何都想循环生成器,那么这似乎是使用生成器的好时机。
This seems like a good time to use generators if your intention is to loop over them anyway.
感谢 Victor 的他/她回答。我尝试改进他/她的答案:
Thank Victor for his/her answer. I tried to improve his/her answer:
下面的代码将为您完成这项工作:
the below code will do the job for you :
使用 String.prototype.match 。
以下是 MDN 文档本身的示例:
Use String.prototype.match.
Here is an example from the MDN docs itself: