我正在尝试在另一个字符串中找到所有出现的字符串的位置,不区分大小写。
例如,给定字符串:
I learned to play the Ukulele in Lebanon.
和搜索字符串le
,我想获取数组:
[2, 25, 27, 33]
两个字符串都是变量 - 也就是说,我不能硬编码它们的值。
我认为对于正则表达式来说这是一项简单的任务,但经过一段时间的努力找到一个可行的表达式之后,我没有运气。
我发现this example如何使用.indexOf()
完成此操作,但肯定有更简洁的方法可以做到这一点吗?
答案 0 :(得分:128)
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>
答案 1 :(得分:14)
这是正则表达式免费版:
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;
}
答案 2 :(得分:11)
你确定可以这样做!
//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
告诉我们针的结束不是开头,但它已经接近了 - 你可以推{{1}进入结果数组......
修改:添加链接
@Tim Down的答案使用了来自RegExp.exec()的结果对象,我的所有Javascript资源都掩饰了它的使用(除了给你匹配的字符串)。因此,当他使用re.lastIndex-needle.length
时,这就是某种未命名的匹配对象。在MDC description of exec中,他们实际上描述了这个对象。
答案 3 :(得分: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)
如果你有一个长度可变的RegExp,它可能不适用,但对某些人来说可能会有所帮助。
答案 4 :(得分:0)
const findAllOccurrences = (str, substr) => {
str = str.toLowerCase();
let result = [];
let idx = str.indexOf(substr)
while (idx !== -1) {
result.push(idx);
idx = str.indexOf(substr, idx+1);
}
return result;
}
console.log(findAllOccurrences('I learned to play the Ukulele in Lebanon', 'le'));
答案 5 :(得分:0)
嗨,朋友们,这只是使用 reduce 和辅助方法查找匹配短语索引的另一种方法。当然,RegExp 更方便,而且可能以某种方式在内部实现。我希望你觉得它有用。
<块引用>function findIndexesOfPhraseWithReduce(text, phrase) {
//convert text to array so that be able to manipulate.
const arrayOfText = [...text];
/* this function takes the array of characters and
the search phrase and start index which comes from reduce method
and calculates the end with length of the given phrase then slices
and joins characters and compare it whith phrase.
and returns True Or False */
function isMatch(array, phrase, start) {
const end = start + phrase.length;
return (array.slice(start, end).join('')).toLowerCase() ===
phrase.toLowerCase();
}
/* here we reduce the array of characters and test each character
with isMach function which takes "current index" and matches the phrase
with the subsequent character which starts from current index and
ends at the last character of phrase(the length of phrase). */
return arrayOfText.reduce((acc, item, index) => isMatch(arrayOfText, phrase,
index) ? [...acc, index] : acc, []);
}
findIndexesOfPhraseWithReduce("I learned to play the Ukulele in Lebanon.", "le");
function findIndexesOfPhraseWithReduce(text, phrase) {
const arrayOfText = [...text];
function isMatch(array, phrase, start) {
const end = start + phrase.length;
return (array.slice(start, end).join('')).toLowerCase() ===
phrase.toLowerCase();
}
return arrayOfText.reduce((acc, item, index) => isMatch(arrayOfText, phrase,
index) ? [...acc, index] : acc, []);
}
console.log(findIndexesOfPhraseWithReduce("I learned to play the Ukulele in Lebanon.", "le"));
答案 6 :(得分:0)
这是我通常用来根据位置获取字符串索引的方法。
我传递以下参数:
search:要搜索的字符串
find:要查找的字符串
position(默认为'all'):查找字符串在搜索字符串中出现的位置
(如果是'all',则返回完整的索引数组)
(如果是'last'则返回最后一个位置)
function stringIndex (search, find, position = "all") {
var currIndex = 0, indexes = [], found = true;
while (found) {
var searchIndex = search.indexOf(find);
if (searchIndex > -1) {
currIndex += searchIndex + find.length;
search = search.substr (searchIndex + find.length);
indexes.push (currIndex - find.length);
} else found = false; //no other string to search for - exit from while loop
}
if (position == 'all') return indexes;
if (position > indexes.length -1) return [];
position = (position == "last") ? indexes.length -1 : position;
return indexes[position];
}
//Example:
var myString = "Joe meets Joe and together they go to Joe's house";
console.log ( stringIndex(myString, "Joe") ); //0, 10, 38
console.log ( stringIndex(myString, "Joe", 1) ); //10
console.log ( stringIndex(myString, "Joe", "last") ); //38
console.log ( stringIndex(myString, "Joe", 5) ); //[]
答案 7 :(得分:0)
这是我的代码(使用搜索和切片方法)
let s = "I learned to play the Ukulele in Lebanon"
let sub = 0
let matchingIndex = []
let index = s.search(/le/i)
while( index >= 0 ){
matchingIndex.push(index+sub);
sub = sub + ( s.length - s.slice( index+1 ).length )
s = s.slice( index+1 )
index = s.search(/le/i)
}
console.log(matchingIndex)
答案 8 :(得分:0)
我参加聚会有点晚了(将近10年零2个月),但是对于将来的编码人员来说,一种方法是使用while循环和indexOf()
let haystack = "I learned to play the Ukulele in Lebanon.";
let needle = "le";
let pos = 0; // Position Ref
let result = []; // Final output of all index's.
let hayStackLower = haystack.toLowerCase();
// Loop to check all occurrences
while (hayStackLower.indexOf(needle, pos) != -1) {
result.push(hayStackLower.indexOf(needle , pos));
pos = hayStackLower.indexOf(needle , pos) + 1;
}
console.log("Final ", result); // Returns all indexes or empty array if not found
答案 9 :(得分:0)
我会推荐蒂姆的答案。但是,@ blazs的this comment表示“假设searchStr=aaa
和那个str=aaaaaa
。然后,除了找到4个事件之外,您的代码只会发现2个,因为您正在通过searchStr.length在循环。”,这是通过查看Tim的代码(尤其是此处的这一行)来实现的:startIndex = index + searchStrLen;
Tim的代码将无法找到所搜索字符串的长度在其长度范围内的实例。因此,我修改了蒂姆的答案:
function getIndicesOf(searchStr, str, caseSensitive) {
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 + 1;
}
return indices;
}
var searchStr = prompt("Enter a string.");
var str = prompt("What do you want to search for in the string?");
var indices = getIndicesOf(str, searchStr);
document.getElementById("output").innerHTML = indices + "";
<div id="output"></div>
如果我具有+ 1
的str和+ searchStrLen
的searchStr,将其更改为aaaaaa
而不是aaa
将使索引1可以位于索引数组中。
P.S。如果有人希望在代码中添加注释以解释代码的工作原理,请这样说,我们将很乐意答复该请求。
答案 10 :(得分:0)
请检查此解决方案,该解决方案也可以找到相同的字符串,让我知道是否缺少某些内容。
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'))
答案 11 :(得分:0)
一个使用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()
,则可以使用for...of
循环运行一百万次迭代(使用您的字符串)。在我的机器上,一个衬线平均1420毫秒,而for...of
平均1150毫秒。这并不是微不足道的区别,但是如果您只进行少量比赛,一支衬板就可以正常工作。
答案 12 :(得分: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
}
答案 13 :(得分: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, []));
答案 14 :(得分:0)
按照@jcubic的回答,他的解决方案对我的案件造成了轻微的混淆
例如$lines = 0;
$z = new ZipArchive();
if ($z->open('path/to/your/archive.zip')) { //make sure you edit this
$fp = $z->getStream('file.php'); //and this according to your file names and path/s
if(!$fp) exit("Couldn't find your file.");
while (!feof($fp)) {
$line = fgets($fp);
$lines++;
}
fclose($fp);
echo $lines; //Total lines counter
}
它将返回var result = indexes('aaaa', 'aa')
而不是[0, 1, 2]
所以我更新了他的解决方案如下,以匹配我的案例
[0, 2]
答案 15 :(得分:0)
以下是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']
答案 16 :(得分:-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")
答案 17 :(得分:-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;
}