Finding all indexes of a specified character within a string
例如,如果我在变量中有
如何以最有效的方式在JavaScript中实现这一点?我不认为循环整个过程是非常有效的
一个简单的循环很好地工作:
1 2 3 4 5 | 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,因为索引是从零开始的。所以你可以添加一个:
1 | if (str[i] ==="s") indices.push(i+1); |
号
现在它会给你预期的结果。
这里可以看到一把小提琴。
I don't think looping through the whole is terribly efficient
号
就表现而言,我不认为这是你需要认真担心的事情,直到你开始遇到问题。
这里是一个比较各种答案的JSPERF测试。在Safari 5.1中,indexof的性能最好。在Chrome19中,for循环是最快的。
。
使用本机
1 2 3 4 5 6 7 8 | 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] |
然而,这是一个微观优化。对于速度足够快的简单而简洁的循环:
1 2 | // 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上本地循环比使用
氧化镁
氧化镁
当我对所有东西进行基准测试时,正则表达式似乎表现得最好,所以我想到了这个
1 2 3 4 5 6 7 8 9 10 11 12 13 | 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; } |
。
你可以这样做
1 | indexesOf('ssssss', /s/g); |
。
哪一个会回来
1 | {s: [0,1,2,3,4,5]} |
我需要一种非常快速的方法来匹配大量文本中的多个字符,例如,您可以这样做
1 | indexesOf('dddddssssss', /s|d/g); |
。
你会得到这个
1 | {d:[0,1,2,3,4], s:[5,6,7,8,9,10]} |
这样,您就可以一次性获取所有匹配项的索引。
1 2 3 4 5 6 7 8 | 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 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | 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] |
。
1 2 3 4 5 | indices = (c, s) => s .split('') .reduce((a, e, i) => e === c ? a.concat(i) : a, []); indices('?', 'a?g??'); // [1, 3, 4] |
号
你也可以使用JavaScript的Matd()函数。您可以创建正则表达式,然后将其作为参数传递给子表达式。
1 | stringName.match(/s/g); |
这将返回一个字母S的所有出现的数组。
我喜欢这个问题,并想通过使用在数组上定义的EDCOX1×3方法来写我的答案。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | function getIndices(text, delimiter='.') { let indices = []; let combined; text.split(delimiter) .slice(0, -1) .reduce((a, b) => { if(a == '') { combined = a + b; } else { combined = a + delimiter + b; } indices.push(combined.length); return combined; // Uncommenting this will lead to syntactical errors }, ''); return indices; } let indices = getIndices(`Ab+Cd+Pk+Djb+Nice+One`, '+'); let indices2 = getIndices(`Program.can.be.done.in.2.ways`); // Here default delimiter will be taken as `.` console.log(indices); // [ 2, 5, 8, 12, 17 ] console.log(indices2); // [ 7, 11, 14, 19, 22, 24 ] // To get output as expected (comma separated) console.log(`${indices}`); // 2,5,8,12,17 console.log(`${indices2}`); // 7,11,14,19,22,24 |