计算Java字符串中字符出现的次数


525

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

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

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

我想找到逗号,字符的数量,即3。以及沿逗号分割后的各个字符串的数量,即4。

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

Answers:


763

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

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月)。我很矛盾,如果我真的需要速度,那我毫无疑问会使用拆分,但我更喜欢使用match。

旧答案(从2009年开始):

如果要查找逗​​号:

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

如果您正在寻找str

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

@Lo的答案和我自己的愚蠢的jsperf测试拆分中,速度至少在Chrome中都领先,但再次创建额外的数组似乎并不理智。


8
测试表明,分割时Firefox比其他任何浏览器都要快得多。jsperf.com/count-the-number-of-occurances-in-string
VSYNC

4
嗯,我刚刚测试了vsync的jsperf,而在Chrome,Firefox和IE中,正则表达式的速度较慢。分别为68%,100%和14%。我有i72600。–
Moss

56
我真的不喜欢使用正则表达式,因为“您更喜欢它”。正则表达式有其目的,但是通常,当有一个简单的非正则表达式解决方案时,它是一个更好的选择。还要注意,这两种方法都会创建一个数组,因此也不是使用正则表达式的原因。
贾斯珀

4
由于某种原因,我在这种情况下更喜欢它。将字符串拆分为数组以获取多次出现是获取信息的一种方法。由于实现细节(可以更改),拆分数组只会更快,而获得匹配数则可以提高可读性,其目的很明显,并且不会创建和填充未使用的数据结构。
比约恩2014年

30
split()是javascript中的基本工具,从概念上讲很简单,对拆分的计数给出明确的意图并且完全可读。
bradw2k 2015年

217

至少有四种方式。最好的选项(由于本地RegEx引擎)也应该是最快的,它位于顶部。jsperf.com目前关闭,否则我将为您提供性能统计信息。

更新:请在此处找到性能测试,并自行运行它们,以贡献您的性能结果。结果的细节将在后面给出。

1。

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

2。

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

不建议拆分。资源匮乏。为每个匹配分配“数组”的新实例。不要通过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的“生成器”,因此不建议使用

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


27
我花了一段时间才意识到自己||[]在做什么,但是这个答案很棒!对于任何人都摸不着头脑,match()返回null如果没有找到匹配,并||[]会返回一个0长度的数组,如果match()回报率null,意义length()将返回0,而不是产生一个错误的类型。
弥敦道

1
内森,为我辩护,在编写上面的代码之前,我做了详细说明:gist.github.com/2757164。我想避免使用小代码段的博客文章,但是这些博客文章使您可以通过google-search进行即时访问。摘要作为摘要存储库的索引非常稀疏,不理想。PS:我也讨厌不清楚的句法特质。
洛伦兹·

2
Lo Sauer,不需要捍卫自己,代码很扎实,我通过弄清楚它是如何工作来自己学到的:)我更喜欢这种方法,而不是实际标记为答案的方法。如果我们不使用结果,则无需拆分字符串。
弥敦道

3
您的第三个方法(也是不幸的是,也是最快的)将丢失大海捞针中索引0处的任何匹配项。您可以使用do ... while循环来解决此问题:var strsearch =“ o”,str =“ othis is foo bar”,index = -1,count = -1; 做{index = str.indexOf(strsearch,index + 1); 数++; } while(索引!= -1); 数
奥古斯

1
足以确定起点index = -2,但非常感谢@Augustus
Lorenz Lo Sauer

18

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

"stringsstringstrings".count("str")呢?
Toskan

12

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
*char(SyntaxError: nothing to repeat)上的错误

1
参数必须是正则表达式。因此,如果您要计算's',则需要发送'[* ]'
Gerard ONeill 17-4-12

8

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

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

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


这基本上是这里必需的答案。我很震惊,没有人指出。
罗希特·古普塔

7

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

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

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


6

我发现,搜索很大字符串(例如,长度为1 000 000个字符)中的字符的最佳方法是使用该replace()方法。

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

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


5

您还可以使用以下方式休息字符串并像处理元素数组一样使用它:

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


1
第二个很方便,谢谢!
AlexGera

4

我对可接受的答案进行了一些改进,它允许使用区分大小写/不区分大小写的匹配进行检查,并且是附加到字符串对象的一种方法:

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

lit 是要搜索的字符串(例如'ex'),而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字符串中的大写字母已包含在搜索中。


4

好的,另一个带有regexp的人-可能不快,但是比其他人简短易读,就我而言'_'

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

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


4

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


4

我发现的最简单方法是...

例-

str = 'mississippi';

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

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

简洁!谢谢!
LeOn-韩立

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


1
是的,它适用于子字符串,不仅适用于子字符。但是,您需要将参数添加到函数中:)
Nico

2

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

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

此方法也适用于数组:

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

2

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

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

在这里您可以找到我的REPL


2

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

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

console.log( 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;
}

console.log( 'example/path/script.js'.charOccurances('/') ); // 2


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

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

1

那么string.split(desiredCharecter).length-1

例:

var str =“让生活变得更美好”; var len = str.split(“ h”)。length-1; 将为上述字符串中的字符“ h”提供计数2;


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


1

这几乎与split和replace方法一样快,它们比regex方法(在chrome中)快一点。

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

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

1

并且有:

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

也可以使用整数!


0

我的解决方案:

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

如果没有匹配项,这将无法作为String.prototype.match回报null。这意味着不引用具有length属性的对象。换句话说:String.prototype.match.call('willnotwork', /yesitwill/) === null
Lorenz Lo Sauer

0

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

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

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

将给出2而不是3,因为过滤器功能布尔值将false表示为0。

其他可能的过滤器功能:

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

0

我知道这可能是个老问题,但是我为JavaScript的低级初学者提供了一个简单的解决方案。

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

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

示例功能:-

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

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表示不存在任何匹配且其版本本身不起作用,因为他忘记提供函数输入参数后,该代码仍会继续寻找匹配项。


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中,您可以使用上述代码来获取字符串中字符的出现。


0

我的ramda js解决方案:

const testString = 'somestringtotest'

const countLetters = R.compose(
  R.map(R.length),
  R.groupBy(R.identity),
  R.split('')
)

countLetters(testString)

链接到REPL。


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;

} 

您忘记了问题的第二部分:“我还需要验证每个字符串,例如str1或str2或str3或str4不应超过15个字符。”
Maxime Launois
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.