查找字符串中指定字符的所有索引

Age*_*eis 56 javascript string indexing

例如,如果我有"scissors"变量,并想知道所有出现的字母的位置"s",它应该打印出来1, 4, 5, 8

如何以最有效的方式在JavaScript中执行此操作?我不认为循环整体是非常有效的

vcs*_*nes 85

一个简单的循环很好:

var str = "scissors";
var indices = [];
for(var i=0; i<str.length;i++) {
    if (str[i] === "s") indices.push(i);
}
Run Code Online (Sandbox Code Playgroud)

现在,您表明您想要1,4,5,8.这将为您提供0,3,4,7,因为索引从零开始.所以你可以添加一个:

if (str[i] === "s") indices.push(i+1);
Run Code Online (Sandbox Code Playgroud)

现在它会给你预期的结果.

这里可以看到小提琴.

我不认为循环整体是非常有效的

就性能而言,在你开始遇到问题之前,我不认为这是你需要非常担心的事情.

这是一个比较各种答案的jsPerf测试.在Safari 5.1中,IndexOf表现最佳.在Chrome 19中,for循环是最快的.

在此输入图像描述

  • 大声笑,我们三个都做了我们自己的JSPerf测试;)请注意,在Chrome上循环更快,但在Firefox和IE上更慢(根据我的测试). (3认同)
  • +1*到目前为止*最快的解决方案.http://jsperf.com/javascript-string-character-finder (2认同)
  • @Phrogz和vcsjones:你们使用`str [i]`就好像100%的crossbrowser兼容性......`charAt()`更可靠 (2认同)

Phr*_*ogz 22

使用本机String.prototype.indexOf方法最有效地查找每个偏移量.

function locations(substring,string){
  var a=[],i=-1;
  while((i=string.indexOf(substring,i+1)) >= 0) a.push(i);
  return a;
}

console.log(locations("s","scissors"));
//-> [0, 3, 4, 7]
Run Code Online (Sandbox Code Playgroud)

然而,这是一种微观优化.对于一个足够快的简单而简洁的循环:

// Produces the indices in reverse order; throw on a .reverse() if you want
for (var a=[],i=str.length;i--;) if (str[i]=="s") a.push(i);    
Run Code Online (Sandbox Code Playgroud)

事实上,原生循环使用的铬更快indexOf!

链接的性能图表


Jou*_*lss 13

在现代浏览器中matchAll完成这项工作:

const string = "scissors";
const matches = [...string.matchAll(/s/g)];
Run Code Online (Sandbox Code Playgroud)

您可以通过多种方式获取这些值。例如 :

const indexes = matches.map(match => match.index);
Run Code Online (Sandbox Code Playgroud)


Cha*_*ira 9

基准

当我对一切进行基准测试时,似乎正则表达式表现得最好,所以我想出了这个

function indexesOf(string, regex) {
    var match,
        indexes = {};

    regex = new RegExp(regex);

    while (match = regex.exec(string)) {
        if (!indexes[match[0]]) indexes[match[0]] = [];
        indexes[match[0]].push(match.index);
    }

    return indexes;
}
Run Code Online (Sandbox Code Playgroud)

你可以这样做

indexesOf('ssssss', /s/g);
Run Code Online (Sandbox Code Playgroud)

哪会回来

{s: [0,1,2,3,4,5]}
Run Code Online (Sandbox Code Playgroud)

我需要一种非常快速的方法来匹配多个字符与大量文本,例如你可以这样做

indexesOf('dddddssssss', /s|d/g);
Run Code Online (Sandbox Code Playgroud)

你会得到这个

{d:[0,1,2,3,4], s:[5,6,7,8,9,10]}
Run Code Online (Sandbox Code Playgroud)

通过这种方式,您可以一次性获得所有匹配的索引

  • 啊,好吧,公平点:),也许您应该将该图表添加到您的答案中,以明确为什么您的解决方案实际上是最有效的。 (2认同)

Tom*_*lak 7

function charPos(str, char) {
  return str
         .split("")
         .map(function (c, i) { if (c == char) return i; })
         .filter(function (v) { return v >= 0; });
}

charPos("scissors", "s");  // [0, 3, 4, 7]
Run Code Online (Sandbox Code Playgroud)

请注意,JavaScript从0开始计数i.如果必须,请添加+1 .

  • +1功能乐趣,即使它与OP所要求的相比,它的效率也很低. (3认同)

dav*_*wil 5

功能更有趣,也更通用:它查找字符串中任意长度的子字符串的起始索引

const length = (x) => x.length
const sum = (a, b) => a+b

const indexesOf = (substr) => ({
  in: (str) => (
    str
    .split(substr)
    .slice(0, -1)
    .map(length)
    .map((_, i, lengths) => (
      lengths
      .slice(0, i+1)
      .reduce(sum, i*substr.length)
    ))
  )  
});

console.log(indexesOf('s').in('scissors')); // [0,3,4,7]

console.log(indexesOf('and').in('a and b and c')); // [2,8]
Run Code Online (Sandbox Code Playgroud)


tpd*_*pdi 5

indices = (c, s) => s
          .split('')
          .reduce((a, e, i) => e === c ? a.concat(i) : a, []);

indices('?', 'a?g??'); // [1, 3, 4]
Run Code Online (Sandbox Code Playgroud)