例如,如果我在可变"scissors"
,想知道这封信"s"
的所有出现的位置,它应该打印出来1, 4, 5, 8
查找字符串中的指定字符的所有指标
我怎样才能做到这一点JavaScript以最有效的方式?我不认为在整个循环是非常有效的
例如,如果我在可变"scissors"
,想知道这封信"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);
现在它会给你你的预期结果。
小提琴可以看here。
我不认为在整个循环是非常有效的
至于性能也越高,我不认为这是你需要严重担心,直到你开始打东西问题。
这是一个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);
事实上,本地环路是快上,使用indexOf
铬!
正如@vcsjones所提到的,如果您(疯狂地)需要基于1的值,您可以'.push(i + 1)'。 – Phrogz
+1,但建议在推送东西后使用反向?使用'unshift()' – ajax333221
@ ajax333221谢谢你;我没有测试'unshift()'的速度,但是对于大数组可能比'.push()'和'.reverse()'慢。 – Phrogz
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开始计数+1按钮添加到i
,如果你一定要。
当我为基准的一切就好像正则表达式进行最好的,所以我想出了这个
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]}
这样你可以得到所有您的匹配的索引在一次去
根据我在chrome上运行的基准,vcsjones仍然是最快的http://jsperf.com/javascript-string-character-finder/6 – IonicBurger
是的一个非常小的字符串,但看看当你增加干草堆时会发生什么:http://jsperf.com/javascript-string-character-finder/7。 Theres没有竞争,在我的情况下,我需要一些能够匹配大量文本而不是小字符串的高性能应用程序。 –
好的公平点:),也许你应该将图表添加到你的答案中,以明确为什么你的解决方案实际上是最有效的。 – IonicBurger
更多功能的乐趣,也更一般:这找到了的任何长度的字符串
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]
加上语法/可读性 –
indices = (c, s) => s
.split('')
.reduce((a, e, i) => e === c ? a.concat(i) : a, []);
indices('?', 'a?g??'); // [1, 3, 4]
你真的不想基于1字符索引,你呢? – Phrogz
除非你有一个大的字符串或大量的字符串,或者这种情况经常发生(像每秒100次),循环遍历整个字符串可能就足够了。重要的不是它有多高效,而是它[*足够快*](http://stackoverflow.com/a/3770194/116614)。 – mellamokb
请注意,角色的位置从'0'开始(不是'1'),这在开始时会引起混淆,但您会自动练习 – ajax333221