在Javascript中统计字符串中字符出现的次数

785
我需要统计一个字符串中某个字符出现的次数。
例如,假设我的���符串包含:
var mainStr = "str1,str2,str3,str4";

我想要找到逗号 , 字符的数量,它是3。以及在逗号分割后的单个字符串的数量,这是4。

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


根据下面排名最高的答案,你也可以使用这个在线工具来交叉检查结果:https://magictools.dev/#!/tools/character-occurences - WJA
39个回答

2

如何理解 string.split(desiredCharecter).length-1?

示例:

var str = "hellow how is life"; var len = str.split("h").length-1; 以上代码中,字符串 "h" 在变量 str 中出现了 2 次。


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


2

String.prototype.reduce = Array.prototype.reduce;

String.prototype.count = function(c) {
    return this.reduce(((n, x) => n + (x === c ? 1 : 0)), 0)
};

const n = "bugs bunny was here".count("b")
console.log(n)

与上面基于原型的代码类似,但不为字符串分配数组。除了循环变体之外,几乎每个以上版本都存在分配问题。这避免了循环代码,重用了浏览器实现的Array.reduce函数。

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

而且还有:

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

也适用于整数!


1

这里有一个与split()和replace方法一样快的方法,它们比正则表达式方法略微快一点(在Chrome和Firefox中都是如此)。

let num = 0;
let str = "str1,str2,str3,str4";
//Note: Pre-calculating `.length` is an optimization;
//otherwise, it recalculates it every loop iteration.
let len = str.length;
//Note: Don't use a `for (... of ...)` loop, it's slow!
for (let charIndex = 0; charIndex < len; ++charIndex) {
  if (str[charIndex] === ',') {
    ++num;
  }
}

哇!对我来说,这比使用split().length - 1方法慢了10倍以上在 FF 浏览器中!这让我很生气! - Andrew
哈哈。我讨厌需要进行性能优化,但是如果速度慢了10倍,那就必须得优化了!Firefox的JIT可能很糟糕,可惜它是我首选的浏览器...坚持住,你永远不知道哪些部分会被优化,哪些不会。 - Gerard ONeill
耶!我解决了!它不喜欢你的for循环。我会更新你的答案;使用常规的for循环,它和split()一样快。我相信原因与此处列出的相同:https://dev59.com/wlcP5IYBdhLWcg3wys-G#43821929 - Andrew
1
安德鲁 - 你不应该改变答案,只需要评论即可。我的原始帖子提供了一个在Chrome上优化(当时)但在Firefox上不是最佳选择的替代方案。这是一种不同的形式,也许有人可能会用得到。你的版本与其他答案相匹配,使我的答案变得无用和被隐藏。我很高兴你设置好了你的算法。然而,我对JavaScript没有足够的投入去改变我的答案。这个注释是为其他人做的历史性评论。请查看原始版本的编辑。 - Gerard ONeill
然而,也许应该做的事情,仍然可以做的是在答案中保留原始答案,但对于那些关心在FF上获得10倍性能提升的人建议我的更改。抱歉,我不是故意冒犯你的。 - Andrew
显示剩余2条评论

1
我正在使用Node.js v.6.0.0,其中最快的方法是索引(Lo Sauer答案中的第3种方法)。
第二种方法是:

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


1

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

将其拆分为数组可以得到一些元素,这些元素的数量始终比字符实例的数量多1。这可能不是最节省内存的方法,但如果您的输入始终很小,这是一种直接且易于理解的方法。
如果您需要解析非常大的字符串(大于几百个字符),或者如果这在处理大量数据的核心循环中,请使用不同的策略。

虽然这段代码可能提供了问题的解决方案,但最好添加上为什么/如何运作的上下文。这可以帮助未来的用户学习并最终将该知识应用到他们自己的代码中。当代码被解释时,您还可能会得到用户的积极反馈/赞同。 - Amit Verma

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

我相信您会发现以下解决方案非常简短、非常快速,能够处理非常长的字符串,支持多个字符搜索,具有错误防护功能,并且能够处理空字符串搜索。

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指示没有匹配项时,代码仍在寻找匹配项,而且他的版本本身也无法工作,因为他忘记提供函数输入参数。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接