簡體   English   中英

Javascript 統計字符串中某個字符出現的次數

[英]Count the number of occurrences of a character in a string in Javascript

我需要計算字符串中某個字符出現的次數。

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

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

我想找到逗號,字符的計數,即 3。以及沿逗號拆分后的單個字符串的計數,即 4。

我還需要驗證每個字符串(即 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

如果您事先知道要搜索的內容,請使用正則表達式文字,否則您可以使用RegExp構造函數,並將g標志作為參數傳入。

match返回null而沒有結果,因此|| [] || []

我在 2009 年做出的原始答案如下。 它不必要地創建了一個數組,但使用拆分更快(截至 2014 年 9 月)。 我很矛盾,如果我真的需要速度,毫無疑問我會使用拆分,但我更喜歡使用匹配。

舊答案(從 2009 年開始):

如果您正在尋找逗號:

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

如果您正在尋找 str

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

在@Lo 的回答和我自己的愚蠢性能測試中,速度都領先,至少在 Chrome 中是這樣,但再次創建額外的數組似乎並不明智。

至少有五種方法。 最好的選項,也應該是最快的(由於本機 RegEx 引擎)放在頂部。

方法一

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

方法二

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

不推薦拆分,因為它很耗資源。 它為每個匹配分配新的 'Array' 實例。 不要嘗試通過 FileReader 獲取 >100MB 的文件。 您可以使用Chrome 的分析器選項觀察確切的資源使用情況。

方法三

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

方法四

搜索單個字符

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

方法五

元素映射和過濾。 不建議這樣做,因為它的整體資源預分配而不是使用 Pythonian 'generators':

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

分享:我提出了這個要點,目前有 8 種字符計數方法,所以我們可以直接匯集和分享我們的想法 - 只是為了好玩,也許還有一些有趣的基准:)

將此函數添加到 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

簡單地說,使用拆分來找出字符串中某個字符的出現次數。

mainStr.split(',').length

mainStr.split(',').length - 1

一個快速的谷歌搜索得到了這個(來自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

您還可以休息您的字符串並像使用元素數組一樣使用它

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

這是一個類似的解決方案,但它使用Array.prototype.reduce

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

如前所述, String.prototype.splitString.prototype.replace工作得快得多。

好的,另一個帶有正則表達式的 - 可能不快,但比其他的短且可讀性更好,在我的情況下只是'_'

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

只需刪除所有看起來不像您的字符但使用字符串作為輸入看起來不好看的所有內容

如果你使用 lodash,_. countBy方法會這樣做:

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

此方法也適用於數組:

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

我發現在非常大的字符串(例如 1 000 000 個字符長)中搜索字符的最佳方法是使用replace()方法。

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

您可以看到另一個 JSPerf套件來測試此方法以及在字符串中查找字符的其他方法。

拆分與正則表達式的性能

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

我對接受的答案做了一點改進,它允許檢查區分大小寫/不區分大小寫的匹配,並且是附加到字符串對象的方法:

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被包含在搜索中。

我發現的最簡單的方法...

例子-

str = 'mississippi';

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

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

這是我的解決方案。 很多解決方案已經在我面前發布。 但我喜歡在這里分享我的觀點。

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

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

我正在做一個需要子字符串計數器的小項目。 搜索錯誤的短語沒有給我任何結果,但是在編寫了自己的實現之后,我偶然發現了這個問題。 無論如何,這是我的方式,它可能比這里的大多數都慢,但可能對某人有幫助:

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

我剛剛使用 Node v7.4 對repl.it做了一個非常快速和骯臟的測試。 對於單個字符,標准 for 循環是最快的:

一些代碼

// 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.301ms
charCount2: 11.652ms
charCount3: 174.043ms
undefined

perfIt()
charCount1: 2.110ms
charCount2: 11.931ms
charCount3: 177.743ms
undefined

perfIt()
charCount1: 2.074ms
charCount2: 11.738ms
charCount3: 152.611ms
undefined

perfIt()
charCount1: 2.076ms
charCount2: 11.685ms
charCount3: 154.757ms
undefined

2021 年 2 月 10 日更新:修復了 repl.it 演示中的錯字

2020 年 10 月 24 日更新Node.js 12 仍然如此(在這里自己玩)

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

例子:

var str = "你好,生活怎么樣"; var len = str.split("h").length-1; 將為上述字符串中的字符“h”提供計數 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

function len(text,char){

return text.innerText.split(string).length
}

console.log(len("str1,str2,str3,str4",","))

這是一個非常簡短的函數。

我知道我在這里聚會遲到了,但我很困惑沒有人用最基本的方法回答這個問題。 社區為這個問題提供的大部分答案都是基於迭代的,但所有答案都是基於每個字符移動字符串,這並不是很有效。

在處理包含數千個字符的大字符串時,遍歷每個字符以獲取出現次數可能變得相當無關緊要,更不用說代碼氣味了。 以下解決方案利用sliceindexOf和受信任的傳統while循環。 這些方法使我們不必遍歷每個字符,並將大大加快計算出現次數的時間。 這些遵循與您在需要字符串遍歷的解析器和詞法分析器中發現的類似邏輯。

與切片一起使用

在這種方法中,我們利用了slice並且對於每個indexOf匹配,我們將在字符串中移動並消除先前搜索的葯水。 每次我們調用indexOf時,它搜索的字符串的大小都會變小。

function countChar (char: string, search: string): number {
  
  let num: number = 0;
  let str: string = search;
  let pos: number = str.indexOf(char);
  
  while(pos > -1) {
    str = str.slice(pos + 1);
    pos = str.indexOf(char);
    num++;
  }

  return num;

}

// Call the function
countChar('x', 'foo x bar x baz x') // 3

從位置與 IndexOf 一起使用

類似於使用slice的第一種方法,但不是增加我們正在搜索的字符串,它將利用indexOf方法中的from參數。

function countChar (char: string, str: string): number {
  
  let num: number = 0;
  let pos: number = str.indexOf(char);
  
  while(pos > -1) {
    pos = str.indexOf(char, pos + 1);
    num++;
  }

  return num;

}

// Call the function
countChar('x', 'foo x bar x baz x') // 3

就我個人而言,我傾向於第二種方法而不是第一種方法,但是在處理大字符串時兩者都很好並且性能更好,但也適用於較小的字符串。

令人驚訝的是,13 年來,這個答案還沒有出現。 直覺上,它似乎應該是最快的:

const s = "The quick brown fox jumps over the lazy dog.";
const oCount = s.length - s.replaceAll('o', '').length;

如果字符串中只有兩種字符,那么這樣更快:


const s = "001101001";
const oneCount = s.replaceAll('0', '').length;

我正在使用 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; }

這是一個與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;
  }
}

還有:

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

也適用於整數!

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

拆分成一個數組給了我們一些元素,這些元素總是比字符實例的數量多 1。 這可能不是最節省內存的,但如果您的輸入總是很小,這是一種直接且易於理解的方法。

如果您需要解析非常大的字符串(超過幾百個字符),或者如果這是在處理大量數據的核心循環中,我會推薦一種不同的策略。

 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 function。

下面使用正則表達式來測試長度。 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.");
}

我的解決方案:

function countOcurrences(str, value){
   var regExp = new RegExp(value, "gi");
   return str.match(regExp) ? str.match(regExp).length : 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;

還有一個答案:

function count(string){
  const count={}
  
  string.split('').forEach(char=>{
    count[char] = count[char] ? (count[char]+1) : 1;
  })
  
  return count
}

console.log(count("abfsdfsddsfdfdsfdsfdsfda"))

我知道這可能是一個老問題,但我為 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;
}

我相信您會發現以下解決方案非常短、非常快、能夠處理非常長的字符串、能夠支持多字符搜索、防錯以及能夠處理空字符串搜索。

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 表示沒有匹配項並且他的版本本身由於他忘記提供函數輸入參數而無法正常工作之后,該代碼仍會繼續尋找匹配項。

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 中,您可以使用上面的代碼來獲取字符串中某個字符的出現。

我使用 ramda js 的解決方案:

const testString = 'somestringtotest'

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

countLetters(testString)

鏈接到 REPL。

該函數將字符串 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;

} 
let str = "aabgrhaab"
let charMap = {}

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

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

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

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

假設上面的示例,要計算正斜杠的數量,您可以這樣做:

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

所以我建議為它使用一個函數(TypeScript):

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

我只是在生成的數組上使用 reduce 函數做到了。 可能不完美,但我喜歡這個。

缺點:只計算單個字符,不計算單詞出現次數。

    let str = "this is a test string";
    let count = [0, ...str].reduce(a, b => a + (b == "s"));
    // returns 4

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

下面這個是最簡單的邏輯,很容易理解

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM