计算Javascript中字符串中出现的字符数

时间:2009-05-19 05:24:25

标签: javascript string

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

例如,假设我的字符串包含:

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

我想找到逗号,字符的计数,即3.以及用逗号分割后的单个字符串的计数,即4。

我还需要验证每个字符串,即str1或str2或str3或str4不应超过15个字符。

35 个答案:

答案 0 :(得分:619)

我已经更新了这个答案。我更喜欢使用匹配的想法,但速度较慢:

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

如果您事先知道要搜索的内容,请使用正则表达式文字,否则可以使用RegExp构造函数,并将g标记作为参数传递。

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

我在2009年做出的原始答案如下。它会不必要地创建一个数组,但使用拆分更快(截至2014年9月)。我很矛盾,如果我真的需要速度那么毫无疑问我会使用分裂,但我宁愿使用匹配。

旧回答(自2009年起):

如果您正在寻找逗号:

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

如果你正在寻找str

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

在@Lo的答案和我自己的愚蠢jsperf test分裂中都有提升速度,至少在Chrome中,但再次创建额外阵列似乎并不健全。

答案 1 :(得分:185)

至少有四种方法。最佳选择,也应该是本机RegEx引擎的最快 - 位于顶部。 jsperf.com目前正在关闭,否则我会为您提供性能统计数据。

更新 :请找到性能测试here,然后自行运行,以便提供效果结果。结果的细节将在稍后给出。

1

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

2

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

拆分不推荐。资源匮乏。为每个匹配分配“Array”的新实例。不要尝试通过FileReader获取> 100MB的文件。您可以使用 Chrome的分析器选项轻松地观察EXACT资源使用情况。

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

搜索单个字符

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

<强>更新

5

元素映射和过滤,由于其整体资源预分配而不是使用Pythonian'generator'而不推荐使用

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

<强>分享: 我创建了这个 gist ,目前有8种字符计数方法,所以我们可以直接汇集和分享我们的想法 - 只是为了好玩,也许是一些有趣的基准:)

https://gist.github.com/2757250

答案 2 :(得分:16)

将此功能添加到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

答案 3 :(得分:9)

快速Google搜索(来自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

答案 4 :(得分:5)

我发现在非常大的字符串中搜索字符的最佳方法(例如,长达1 000 000个字符)是使用replace()方法。

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

您可以看到yet another JSPerf套件来测试此方法以及在字符串中查找字符的其他方法。

答案 5 :(得分:4)

好吧,另一个有regexp的人 - 可能不是很快,但是简短且比其他人更易读,在我的情况下只需'_'来计算

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

删除所有看起来不像你的char的东西 但是使用字符串作为输入看起来不太好看

答案 6 :(得分:4)

只需使用拆分找出字符串中字符的出现次数。

mainStr.split(',').length //给出4这是使用分隔符逗号分割后的字符串数

mainStr.split(',').length - 1 //给出3这是逗号的计数

答案 7 :(得分:4)

Split vs. 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");

答案 8 :(得分:4)

这是一个类似的解决方案,但它使用Array.ptototype.reduce

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

如上所述,String.prototype.split的工作速度比String.prototype.replace快得多。

答案 9 :(得分:3)

我正在开发一个需要子字符串计数器的小项目。搜索错误的短语没有给我带来任何结果,但是在编写了我自己的实现后,我偶然发现了这个问题。无论如何,这是我的方式,它可能比大多数人慢,但可能对某人有帮助:

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/

如果您发现此实施失败或未遵循某些标准,请告诉我们! :)

<强>更新 您可能想要替换:

    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

答案 10 :(得分:3)

我对接受的答案略有改进,它允许检查区分大小写/不区分大小写的匹配,并且是附加到字符串对象的方法:

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

lit是要搜索的字符串(例如&#39; ex&#39;),cis是不区分大小写的,默认为false,它允许选择不区分大小写的匹配项。

<小时/> 要在字符串'I love StackOverflow.com'中搜索小写字母'o',您可以使用:

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

amount_of_os等于2

<小时/> 如果我们使用不区分大小写的匹配再次搜索相同的字符串,您将使用:

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

这一次,amount_of_os将等于3,因为字符串中的大写O会包含在搜索中。

答案 11 :(得分:3)

我发现最容易的方式......

实施例 -

str = 'mississippi';

function find_occurences(str, char_to_count){
    return str.split(char_to_count).length - 1;
}

find_occurences(str, 'i') //outputs 4

答案 12 :(得分:2)

您还可以rest使用字符串并像使用元素数组一样使用它

const mainStr = 'str1,str2,str3,str4';
const commas = [...mainStr].filter(l => l === ',').length;

console.log(commas);

const mainStr = 'str1,str2,str3,str4';
const commas = [...mainStr].reduce((a, c) => c === ',' ? ++a : a, 0);

console.log(commas);

答案 13 :(得分:2)

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

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

此方法也适用于数组:

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

答案 14 :(得分:1)

有:

function character_count(string, char, ptr = 0, count = 0) {
    while (ptr = string.indexOf(char, ptr) + 1) {count ++}
    return count
}

也可以使用整数!

答案 15 :(得分:1)

var mainStr = "str1,str2,str3,str4";
var splitStr = mainStr.split(",").length - 1; // subtracting 1 is important!
alert(splitStr);

拆分成一个数组给了我们许多元素,这些元素总是比字符的实例数多 1。这可能不是最有效的内存效率,但如果您的输入总是很小,这是一种直接且易于理解的方法。

如果您需要解析非常大的字符串(超过几百个字符),或者如果这是在处理大量数据的核心循环中,我会推荐不同的策略。

答案 16 :(得分:1)

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

部分代码

// 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

答案 17 :(得分:1)

这是一个几乎和split和replace方法一样快的方法,它比正则表达式方法(在chrome中)快一点。

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

答案 18 :(得分:1)

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

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.");
}

答案 19 :(得分:1)

string.split(desiredCharecter).length-1

怎么样?

示例:

var str =“hellow life is life”; var len = str.split(“h”)。length-1;将在上面的字符串中给出字符“h”的计数2;

答案 20 :(得分:1)

我正在使用Node.js v.6.0.0,最快的是带索引的那个(Lo Sauer的答案中的第三种方法)。

第二个是:

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

答案 21 :(得分:1)

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

答案 22 :(得分:0)

我的解决方案:

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

答案 23 :(得分:0)

有一个非常棘手的方法,但它是相反的:

const sampleStringText = "/john/dashboard/language";

假设上面的例子,为了计算正斜杠的数量,你可以这样做:

console.log( sampleStringText.split('/') - 1 );

所以我建议为它使用一个函数(TypeScript):

const counter = (sentence: string, char: string): number => sentence.split(char) - 1;

答案 24 :(得分:0)

let str = "aabgrhaab"
let charMap = {}

for(let char of text) {
   if(charMap.hasOwnProperty(char)){
      charMap[char]++
   } else {
     charMap[char] = 1
   }
}

console.log(charMap); // {a:4,b:2,g:1,r:1,h:1}

答案 25 :(得分:0)

这是我的解决方案。许多解决方案已经摆在我面前。但我喜欢在这里分享我的观点。

const mainStr = 'str1,str2,str3,str4';

const commaAndStringCounter = (str) => {
  const commas = [...str].filter(letter => letter === ',').length;
  const numOfStr = str.split(',').length;

  return `Commas: ${commas}, String: ${numOfStr}`;
}

// Run the code
console.log(commaAndStringCounter(mainStr)); // Output: Commas: 3, String: 4

Here you find my REPL

答案 26 :(得分:0)

该函数将字符串str作为参数,并对字符串中每个唯一字符的出现进行计数。结果进入每个字符的键-值对。

var charFoundMap = {};//object defined
    for (var i = 0; i < str.length; i++) {

       if(!charFoundMap[ str[i] ])  {
        charFoundMap[ str[i] ]=1;
       } 
       else
       charFoundMap[ str[i] ] +=1;
       //if object does not contain this 
    }
    return charFoundMap;

} 

答案 27 :(得分:0)

我的ramda js解决方案:

And

Link to REPL.

答案 28 :(得分:0)

var a = "acvbasbb";
var b= {};
for (let i=0;i<a.length;i++){
    if((a.match(new RegExp(a[i], "g"))).length > 1){
        b[a[i]]=(a.match(new RegExp(a[i], "g"))).length;
    }
}
console.log(b);

在javascript中,您可以使用上面的代码来获取字符串中字符的出现。

答案 29 :(得分:0)

最快的方法似乎是通过索引运算符:

function charOccurances (str, char)
{
    for (var c = 0, i = 0, len = str.length; i < len; ++i)
    {
        if (str[i] == char)
        {
            ++c;
        }
    }
    return c;
}

用法:

charOccurances('example/path/script.js', '/') == 2

或作为原型功能:

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

用法:

charOccurances('example/path/script.js', '/') == 2

答案 30 :(得分:0)

我相信您会发现以下解决方案非常简短,非常快,能够使用非常长的字符串,能够支持多个字符搜索,错误证明以及能够处理空字符串搜索。

function substring_count(source_str, search_str, index) {
    source_str += "", search_str += "";
    var count = -1, index_inc = Math.max(search_str.length, 1);
    index = (+index || 0) - index_inc;
    do {
        ++count;
        index = source_str.indexOf(search_str, index + index_inc);
    } while (~index);
    return count;
}

使用示例:

console.log(substring_count("Lorem ipsum dolar un sit amet.", "m "))

function substring_count(source_str, search_str, index) {
    source_str += "", search_str += "";
    var count = -1, index_inc = Math.max(search_str.length, 1);
    index = (+index || 0) - index_inc;
    do {
        ++count;
        index = source_str.indexOf(search_str, index + index_inc);
    } while (~index);
    return count;
}

上面的代码解决了Jakub Wawszczyk中的主要性能错误,即使在indexOf表示没有并且他的版本本身无法工作因为忘记给出函数输入参数之后,代码仍会查找匹配。

答案 31 :(得分:0)

我知道这可能是一个老问题,但我有一个简单的解决方案,适用于JavaScript中的低级初学者。

作为初学者,我只能理解这个问题的一些解决方案,所以我使用两个嵌套的 FOR 循环来检查字符串中每个其他字符的每个字符,增加计数找到的每个字符的变量等于该字符。

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

示例功能: -

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;
}

答案 32 :(得分:0)

如果角色位于字符串的开头,则Leo Sauers的第五种方法回答失败。 例如

var needle ='A',
  haystack = 'AbcAbcAbc';

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

将给出2而不是3,因为过滤器函数Boolean为0提供false。

其他可能的过滤功能:

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

答案 33 :(得分:-1)

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");

答案 34 :(得分:-1)

下面是最简单的逻辑,很容易理解

  //Demo string with repeat char 
  let str = "Coffee"
  //Splitted the str into an char array for looping
  let strArr = str.split("")
  //This below is the final object which holds the result
  let obj = {};
  //This loop will count char (You can also use traditional one for loop)
  strArr.forEach((value,index)=>{
      //If the char exists in the object it will simple increase its value
      if(obj[value] != undefined)
      {
          obj[value] = parseInt(obj[value]) + 1;
      }//else it will add the new one with initializing 1
      else{
          obj[value] =1;
      }      
  });

  console.log("Char with Count:",JSON.stringify(obj)); //Char with Count:{"C":1,"o":1,"f":2,"e":2}