计算Javascript中string出现的次数

我需要计算一个string中字符的出现次数。

例如,假设我的string包含:

var mainStr = "str1,str2,str3,str4"; 

我想find逗号,字符的数量,这是3.和单个string的计数,沿着逗号分割,这是4。

我还需要validation每个string(即str1或str2或str3或str4)不应该超过15个字符。

我已经更新了这个答案。 我更喜欢使用比赛的想法,但比较慢:

 console.log(("str1,str2,str3,str4".match(/,/g) || []).length); //logs 3 console.log(("str1,str2,str3,str4".match(new RegExp("str", "g")) || []).length); //logs 4 

的jsfiddle

如果您事先知道要search的内容,请使用正则expression式,如果不是,则可以使用RegExp构造函数,并将g标志作为参数传入。

match返回null ,没有结果,因此|| [] || []

我在2009年的原始答案如下。 它不必要地创build一个数组,但使用拆分更快 (截至2014年9月)。 我很矛盾,如果我真的需要这个速度,那么我不会用分裂,但是我更喜欢使用匹配。

旧的答案(从2009年起):

如果你正在寻找逗号:

 (mainStr.split(",").length - 1) //3 

如果你正在寻找str

 (mainStr.split("str").length - 1) //4 

无论是在@ Lo的回答还是在我自己愚蠢的jsperftesting中,至less在Chrome中都是如此,但是再次创build额外的数组似乎并不理智。

至less有四种方法。 最好的select,也应该是最快的原生RegEx引擎,放在顶部。 jsperf.com目前正在下降,否则我会为您提供性能统计。

更新 :请在这里find性能testing,并自行运行,以便贡献您的性能结果。 结果的细节将在稍后给出。

1。

  ("this is foo bar".match(/o/g)||[]).length //>2 

2。

 "this is foo bar".split("o").length-1 //>2 

拆分不build议。 资源饿了。 为每个匹配分配“Array”的新实例。 不要试图通过FileReader> 100MB的文件。 您可以使用Chrome的分析器选项轻松观察到精确的资源使用情况。

3。

 var stringsearch = "o" ,str = "this is foo bar"; for(var count=-1,index=-2; index != -1; count++,index=str.indexOf(stringsearch,index+1) ); //>count:2 

4。

search单个字符

 var stringsearch = "o" ,str = "this is foo bar"; for(var i=count=0; i<str.length; count+=+(stringsearch===str[i++])); //>count:2 

更新:

5。

元素映射和过滤,由于其整体资源预分配而不是使用Pythonian“生成器”

 var str = "this is foo bar" str.split('').map( function(e,i){ if(e === 'o') return i;} ) .filter(Boolean) //>[9, 10] [9, 10].length //>2 

分享:我做了这个要点 ,目前有8种字符计算方法,所以我们可以直接汇集和分享我们的想法 – 只是为了好玩,也许还有一些有趣的基准:)

https://gist.github.com/2757250

一个快速的谷歌search得到了这个(从http://www.codecodex.com/wiki/index.php?title=Count_the_number_of_occurrences_of_a_specific_character_in_a_string#JavaScript

 String.prototype.count=function(s1) { return (this.length - this.replace(new RegExp(s1,"g"), '').length) / s1.length; } 

像这样使用它:

 test = 'one,two,three,four' commas = test.count(',') // returns 3 

将这个函数添加到sting原型中:

 String.prototype.count=function(c) { var result = 0, i = 0; for(i;i<this.length;i++)if(this[i]==c)result++; return result; }; 

用法:

 console.log("strings".count("s")); //2 

好吧,另一个与正则expression式 – 可能不快,但短,更好的可读性,其他人,在我的情况下只是'_'来计数

 key.replace(/[^_]/g,'').length 

只是删除看起来不像你的字符的东西,但它不像一个string作为input看起来不错

我发现search一个非常大的string(例如,长度为1000000字符replace()方法是使用replace()方法。

 window.count_replace = function (str, schar) { return str.length - str.replace(RegExp(schar), '').length; }; 

你可以看到另外一个JSPerf套件来testing这个方法以及其他在string中查找字符的方法。

我正在做一个需要一个子string计数器的小项目。 search错误的短语没有给我提供任何结果,但是在编写我自己的实现之后,我偶然发现了这个问题。 无论如何,这是我的方式,它可能比大多数这里慢,但可能有助于某人:

 function count_letters() { var counter = 0; for (var i = 0; i < input.length; i++) { var index_of_sub = input.indexOf(input_letter, i); if (index_of_sub > -1) { counter++; i = index_of_sub; } } 

http://jsfiddle.net/5ZzHt/1/

请让我知道,如果你发现这个实现失败或不遵循一些标准! 🙂

更新您可能需要replace:

  for (var i = 0; i < input.length; i++) { 

附:

 for (var i = 0, input_length = input.length; i < input_length; i++) { 

有趣的阅​​读讨论上述: http : //www.erichynds.com/blog/javascript-length-property-is-a-stored-value

我对接受的答案做了一些改进,它允许检查区分大小写的和不区分大小写的匹配,并且是一个附加到string对象的方法:

 String.prototype.count = function(lit, cis) { var m = this.toString().match(new RegExp(lit, ((cis) ? "gi" : "g"))); return (m != null) ? m.length : 0; } 

lit是要search的string(如“ex”),而cis是不区分大小写的,默认为false,允许select不区分大小写的匹配。


要searchstring'I love StackOverflow.com'为小写字母'o' ,您可以使用:

 var amount_of_os = 'I love StackOverflow.com'.count('o'); 

amount_of_os将等于2


如果我们要使用不区分大小写的匹配再次search相同的string,则可以使用:

 var amount_of_os = 'I love StackOverflow.com'.count('o', true); 

这次, amount_of_os将等于3 ,因为string中的大写amount_of_os O包含在search中。

性能分割与RegExp

 var i = 0; var split_start = new Date().getTime(); while (i < 30000) { "1234,453,123,324".split(",").length -1; i++; } var split_end = new Date().getTime(); var split_time = split_end - split_start; i= 0; var reg_start = new Date().getTime(); while (i < 30000) { ("1234,453,123,324".match(/,/g) || []).length; i++; } var reg_end = new Date().getTime(); var reg_time = reg_end - reg_start; alert ('Split Execution time: ' + split_time + "\n" + 'RegExp Execution time: ' + reg_time + "\n"); 

我find最简单的方法

例-

 str = 'mississippi'; function find_occurences(str, char_to_count){ return str.split(char_to_count).length - 1; } find_occurences(str, 'i') //outputs 4 

这里是一个类似的解决scheme,但它使用减less

 function countCharacters(char, string) { return string.split('').reduce((acc, ch) => ch === char ? acc + 1: acc, 0) } 

如前所述,拆分比replace快得多。

 s = 'dir/dir/dir/dir/' for(i=l=0;i<s.length;i++) if(s[i] == '/') l++ 

怎么样string.split(desiredCharecter).length-1

例:

var str =“hellow生活怎么样”; var len = str.split(“h”)。length-1; 在上面的string中会给字符“h”计2;

我使用Node.js v6.0.0,最快的是索引(Lo Sauer的答案中的第三种方法)。

第二个是:

 function count(s, c) { var n = 0; for (let x of s) { if (x == c) n++; } return n; } 

如果您使用lodash, _.countBy方法将执行此操作:

 _.countBy("abcda")['a'] //2 

这个方法也适用于数组:

 _.countBy(['ab', 'cd', 'ab'])['ab'] //2 

这几乎和拆分和replace方法一样快,这比正则expression式方法(在chrome中)要快一点。

 var num = 0; for (ch of "str1,str2,str3,str4") { if (ch === ',') num++; } 

以下使用正则expression式来testing长度。 testex确保您没有16个或更多连续的非逗号字符。 如果通过testing,则继续分割string。 计算逗号就像计算令牌减1一样简单。

 var mainStr = "str1,str2,str3,str4"; var testregex = /([^,]{16,})/g; if (testregex.test(mainStr)) { alert("values must be separated by commas and each may not exceed 15 characters"); } else { var strs = mainStr.split(','); alert("mainStr contains " + strs.length + " substrings separated by commas."); alert("mainStr contains " + (strs.length-1) + " commas."); } 

我的解决scheme

 function countOcurrences(str, value){ var regExp = new RegExp(value, "gi"); return str.match(regExp) ? str.match(regExp).length : 0; } 

我只是使用Node v7.4对repl.it进行了一个非常快速和肮脏的testing。 对于单个字符,循环的标准是最快的:

一些代码

 // winner! function charCount1(s, c) { let count = 0; c = c.charAt(0); // we save some time here for(let i = 0; i < s.length; ++i) { if(c === s.charAt(i)) { ++count; } } return count; } function charCount2(s, c) { return (s.match(new RegExp(c[0], 'g')) || []).length; } function charCount3(s, c) { let count = 0; for(ch of s) { if(c === ch) { ++count; } } return count; } function perfIt() { const s = 'Hello, World!'; const c = 'o'; console.time('charCount1'); for(let i = 0; i < 10000; i++) { charCount1(s, c); } console.timeEnd('charCount1'); console.time('charCount2'); for(let i = 0; i < 10000; i++) { charCount2(s, c); } console.timeEnd('charCount2'); console.time('charCount3'); for(let i = 0; i < 10000; i++) { charCount2(s, c); } console.timeEnd('charCount3'); } 

几次运行的结果

  perfIt() charCount1: 3.843ms charCount2: 11.614ms charCount3: 11.470ms => undefined perfIt() charCount1: 3.006ms charCount2: 8.193ms charCount3: 7.941ms => undefined perfIt() charCount1: 2.539ms charCount2: 7.496ms charCount3: 7.601ms => undefined perfIt() charCount1: 2.654ms charCount2: 7.540ms charCount3: 7.424ms => undefined perfIt() charCount1: 2.950ms charCount2: 9.445ms charCount3: 8.589ms 

如果字符在string的开头,则Leo Sauers中的第五种方法失败。 例如

 var needle ='A', haystack = 'AbcAbcAbc'; haystack.split('').map( function(e,i){ if(e === needle) return i;} ) .filter(Boolean).length; 

会给2而不是3,因为过滤function布尔值为0时为false。

其他可能的过滤function:

 haystack.split('').map(function (e, i) { if (e === needle) return i; }).filter(function (item) { return !isNaN(item); }).length; 

我知道这可能是一个老问题,但我有一个简单的解决scheme,在JavaScript的低级初学者。

作为初学者,我只能理解这个问题的一些解决scheme,所以我使用了两个嵌套的FOR循环来检查string中每个其他字符的每个字符,为每个find的字符增加一个countvariables。

我创build了一个新的空白对象,其中每个属性键都是一个字符,值是每个字符在string(count)中出现的次数。

示例function: –

 function countAllCharacters(str) { var obj = {}; if(str.length!==0){ for(i=0;i<str.length;i++){ var count = 0; for(j=0;j<str.length;j++){ if(str[i] === str[j]){ count++; } } if(!obj.hasOwnProperty(str[i])){ obj[str[i]] = count; } } } return obj; }