例如,如果我有"scissors"
in 变量并想知道所有出现的字母的位置"s"
,它应该打印出1, 4, 5, 8
.
我怎样才能以最有效的方式在 JavaScript 中做到这一点?我不认为遍历整个过程非常有效
例如,如果我有"scissors"
in 变量并想知道所有出现的字母的位置"s"
,它应该打印出1, 4, 5, 8
.
我怎样才能以最有效的方式在 JavaScript 中做到这一点?我不认为遍历整个过程非常有效
一个简单的循环效果很好:
var str = "scissors";
var indices = [];
for(var i=0; i<str.length;i++) {
if (str[i] === "s") indices.push(i);
}
现在,您表明您想要 1、4、5、8。这将为您提供 0、3、4、7,因为索引是从零开始的。所以你可以添加一个:
if (str[i] === "s") indices.push(i+1);
现在它会给你你预期的结果。
一个小提琴可以在这里看到。
我不认为遍历整个过程非常有效
就性能而言,我不认为这是您在开始遇到问题之前需要严重担心的事情。
这是一个比较各种答案的jsPerf测试。在 Safari 5.1 中,IndexOf 表现最好。在 Chrome 19 中,for 循环是最快的。
使用本机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]
然而,这是一个微观优化。对于一个足够快的简单而简洁的循环:
// 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);
事实上,原生循环在 chrome 上比使用indexOf
!
当我对所有内容进行基准测试时,正则表达式似乎表现最好,所以我想出了这个
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;
}
你可以这样做
indexesOf('ssssss', /s/g);
哪个会返回
{s: [0,1,2,3,4,5]}
我需要一种非常快速的方法来将多个字符与大量文本进行匹配,例如您可以这样做
indexesOf('dddddssssss', /s|d/g);
你会得到这个
{d:[0,1,2,3,4], s:[5,6,7,8,9,10]}
通过这种方式,您可以一次性获得所有匹配项的索引
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]
请注意,JavaScript 从 0 开始计数i
。如果必须,请将+1 添加到。
功能更有趣,也更通用:这将查找字符串中任意长度的子字符串的起始索引
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]