Javascript에서 문자열의 문자 발생 횟수를 계산하십시오.


525

문자열에서 문자의 발생 횟수를 계산해야합니다.

예를 들어 내 문자열에 다음이 포함되어 있다고 가정합니다.

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

쉼표 ,문자 수인 3 을 찾고 싶습니다 . 쉼표를 따라 분할 한 후 개별 문자열의 수는 4입니다.

또한 각 문자열 즉, str1 또는 str2 또는 str3 또는 str4가 15자를 초과하지 않아야하는지 확인해야합니다.

답변:


765

이 답변을 업데이트했습니다. 일치를 더 잘 사용한다는 아이디어가 마음에 들지만 속도가 느립니다.

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플래그를 인수로 전달하십시오.

matchnull결과없이 반환|| []

내가 2009 년에 한 원래 답변은 다음과 같습니다. 불필요하게 배열을 생성하지만 분할을 사용하는 것이 더 빠릅니다 (2014 년 9 월 기준). 나는 속도를 정말로 필요로한다면 스플릿을 사용한다는 데는 의문의 여지가 없지만 일치하는 것을 선호합니다.

기존 답변 (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 %입니다. 나는 i7 2600을 가지고 있습니다.
Moss

56
"정말 좋아"때문에 정규식을 사용한다는 생각이 정말 마음에 들지 않습니다. 정규 표현식은 목적이 있지만 일반적으로 간단한 비정규 솔루션이있는 경우 더 나은 선택입니다. 또한 두 방법 모두 배열을 생성하므로 정규 표현식을 사용해야하는 이유는 아닙니다.
Jasper

4
나는 이유 에서 더 좋아 . 문자열을 배열로 분할하여 여러 번 발생하는 것은 해당 정보를 얻는 방법입니다. 구현 세부 사항, 변경 가능한 변경 사항으로 인해 배열을 나누는 것이 더 빠르지 만 일치 횟수를 얻는 것이 가독성이 향상되고 의도는 분명하며 사용되지 않는 데이터 구조를 작성하고 채우지 않습니다.
Bjorn

30
split ()은 자바 스크립트의 기본 도구로 개념적으로 간단하며 분할을 계산하면 의도가 분명하고 완전히 읽을 수 있습니다.
bradw2k

217

네 가지 방법이 있습니다. 기본 RegEx 엔진으로 인해 가장 빠른 옵션이 맨 위에 배치됩니다. jsperf.com이 현재 작동 중지되었습니다. 그렇지 않으면 성능 통계를 제공합니다.

업데이트 : 여기 에서 성능 테스트를 찾아서실행하여 성능 결과에 기여하십시오. 결과의 세부 사항은 나중에 제공됩니다.

1.

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

2.

"this is foo bar".split("o").length-1
 //>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) );
 //>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 '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
//>2

공유 : 나는 현재 8 가지 캐릭터 카운팅 방법 으로이 요점을 만들었 으므로 재미를 위해 아이디어를 모아 공유 할 수 있습니다.

https://gist.github.com/2757250


27
무엇 ||[]을하고 있는지 깨닫는 데 조금 시간이 걸렸지 만이 답변은 훌륭합니다! 다른 그들의 머리를 긁적 누군가를 위해, match()수익률은 null더 일치가 발견되지 않으며 경우 ||[]경우 길이가 0 인 배열을 반환합니다 match()반환 null, 의미 length()유형의 오류를 생성하는 대신 0을 반환합니다.
나단

1
Nathan은 위의 코드를 작성하기 전에 gist.github.com/2757164에서 자세히 설명했습니다 . 작은 코드 조각의 블로그 게시물을 피하고 싶지만 Google 검색을 통해 즉시 액세스 할 수 있습니다. 스 니펫 저장소로서의 요점은 매우 드물게 색인되어 있으며 이상적이지 않습니다. 추신 : 나도 불분명 한 구문 특질을 싫어합니다.
Lorenz Lo Sauer

2
Lo Sauer, 자신을 방어 할 필요가 없으며 코드가 견고하며 작동 방식을 알아내어 스스로 학습했습니다. :) 실제로 답변으로 표시된 것 보다이 방법을 선호합니다. 결과를 사용하지 않을 경우 문자열을 분리 할 필요가 없습니다.
Nathan

3
세 번째 방법 (아쉽게도 가장 빠름)은 건초 더미에서 인덱스 0에서 일치하는 항목을 놓치게됩니다. 대신 do ... while 루프를 사용하여 문제를 해결할 수 있습니다. var strsearch = "o", str = "othis is foo bar", index = -1, count = -1; {index = str.indexOf (strsearch, index + 1); 카운트 ++; } while (인덱스! = -1); 카운트
Augustus

1
그것은 시작을 설정하는 것으로 충분 index = -2하지만, 감사합니다 @Augustus
Lorenz Lo Sauer

18

이 기능을 쏘는 프로토 타입에 추가하십시오 :

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
인수는 정규식이어야합니다. 따라서의 수를 세려면 '[* ]'로
보내셔야합니다

8

간단히, split 을 사용하여 문자열에서 문자의 발생 횟수를 찾으십시오.

mainStr.split(',').length // 구분 기호 쉼표를 사용하여 분할 한 후 문자열 수인 4를 제공합니다. // 쉼표의 수인

mainStr.split(',').length - 1 3을 제공합니다.


이것은 기본적으로 여기에 필요한 답변입니다. 아직 지적한 사람이 아무도 없습니다.
Rohit Gupta

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 제품군을 볼 수 있습니다 .


코드가 어떻게 든 초당 500000 회 이상 백만 문자를 반복하는 경우 내 CPU가 최소 100GHz에서 실행되고 있습니다 (SIMD가 없다고 가정하더라도 40GHz 이상임). 따라서 나는이 벤치 마크가 정확하다고 생각하지 않습니다.
내 대명사는

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입니다 .3O


4

좋아, regexp를 가진 다른 하나-아마도 빠르지는 않지만 짧고 더 잘 읽을 '_'수 있습니다.

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

당신의 숯불처럼 보이지 않는 모든 것을 제거하지만 문자열이 입력으로 좋지 않은 것처럼 보입니다.


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


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-Han Li

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 개 이상의 연속적인 비 쉼표 문자가 없도록합니다. 테스트를 통과하면 문자열 분할이 진행됩니다. 쉼표를 계산하는 것은 토큰에서 빼기 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.");
}

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 방법 (크롬)보다 약간 빠릅니다.

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

1

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

필터 함수 부울이 0에 대해 false를 제공하므로 3 대신 2를 제공합니다.

다른 가능한 필터 기능 :

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

자바 스크립트에서는 위의 코드를 사용하여 문자열에 문자가 나타날 수 있습니다.


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 2016 년
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.