web-dev-qa-db-ja.com

文字列内で文字列の出現回数を数える方法

特定の文字列が別の文字列に現れる回数を数える方法はありますか。例えば、これは私がJavascriptでやろうとしていることです:

var temp = "This is a string.";
alert(temp.count("is")); //should output '2'
500
TruMan1

正規表現内のg global の略)は、最初の出現箇所を見つけるのではなく、文字列全体を検索するように指示します。これはisと2回一致します。

var temp = "This is a string.";
var count = (temp.match(/is/g) || []).length;
console.log(count);

そして、一致するものがなければ、0を返します。

var temp = "Hello World!";
var count = (temp.match(/is/g) || []).length;
console.log(count);
862
/** Function that count occurrences of a substring in a string;
 * @param {String} string               The string
 * @param {String} subString            The sub string to search for
 * @param {Boolean} [allowOverlapping]  Optional. (Default:false)
 *
 * @author Vitim.us https://Gist.github.com/victornpb/7736865
 * @see Unit Test https://jsfiddle.net/Victornpb/5axuh96u/
 * @see http://stackoverflow.com/questions/4009756/how-to-count-string-occurrence-in-string/7924240#7924240
 */
function occurrences(string, subString, allowOverlapping) {

    string += "";
    subString += "";
    if (subString.length <= 0) return (string.length + 1);

    var n = 0,
        pos = 0,
        step = allowOverlapping ? 1 : subString.length;

    while (true) {
        pos = string.indexOf(subString, pos);
        if (pos >= 0) {
            ++n;
            pos += step;
        } else break;
    }
    return n;
}

使用法

occurrences("foofoofoo", "bar"); //0

occurrences("foofoofoo", "foo"); //3

occurrences("foofoofoo", "foofoo"); //1

allowOverlapping

occurrences("foofoofoo", "foofoo", true); //2

一致します。

  foofoofoo
1 `----´
2    `----´

単体テスト

基準

私はベンチマークテストをしました、そして、私の機能はgumboによって掲示された正規表現マッチ機能より10倍以上速いです。私のテスト文字列では25文字の長さです。 'o'が2回出現する。 Safariで1 000 000回実行しました。

Safari 5.1

ベンチマーク>合計実行時間:5617 ms(正規表現)

ベンチマーク>合計実行時間:881ミリ秒(私の機能6.4倍高速)

Firefox 4

ベンチマーク>合計実行時間:8547ミリ秒(Rexexp)

ベンチマーク>総実行時間:634ミリ秒(私の機能は13.5倍高速)


編集:私が加えた変更

  • キャッシュされた部分文字列の長さ

  • 文字列に型キャストを追加しました。

  • オプションの 'allowOverlapping'パラメータを追加しました

  • 空の部分文字列の場合の正しい出力を修正しました。

213
Vitim.us
function countInstances(string, Word) {
   return string.split(Word).length - 1;
}
93
Orbit

これを試すことができます:

var theString = "This is a string.";
console.log(theString.split("is").length - 1);
75
Freezy Ize

私の解決策:

var temp = "This is a string.";

function countOcurrences(str, value) {
  var regExp = new RegExp(value, "gi");
  return (str.match(regExp) || []).length;
}

console.log(countOcurrences(temp, 'is'));
32
Gere

そのような関数を定義するためにmatchを使うことができます。

String.prototype.count = function(search) {
    var m = this.match(new RegExp(search.toString().replace(/(?=[.\\+*?[^\]$(){}\|])/g, "\\"), "g"));
    return m ? m.length:0;
}
18
Gumbo

ただコードゴルファー Rebecca Chernoff :-)

alert(("This is a string.".match(/is/g) || []).length);
9
TMS

非正規表現バージョン:

 var string = 'This is a string',
    searchFor = 'is',
    count = 0,
    pos = string.indexOf(searchFor);

while (pos > -1) {
    ++count;
    pos = string.indexOf(searchFor, ++pos);
}

console.log(count);   // 2
9
Faraz Kelhini

これが最速の機能です。

なぜそれが速いのですか?

  • Charごとにcharをチェックしません(1つの例外を除いて)
  • Whileを使用し、長さをチェックして2 varsを増分するforループに対して1 var(char count var)を増分します(通常、var iおよびchar countを持つvar)。
  • WAY less varsを使用します
  • 正規表現を使いません!
  • (うまくいけば)高度に最適化された関数を使用します
  • すべての操作が可能な限り組み合わされ、複数の操作によるスローダウンを回避

    String.prototype.timesCharExist=function(c){var t=0,l=0,c=(c+'')[0];while(l=this.indexOf(c,l)+1)++t;return t};
    

これは遅くて読みやすいバージョンです。

    String.prototype.timesCharExist = function ( chr ) {
        var total = 0, last_location = 0, single_char = ( chr + '' )[0];
        while( last_location = this.indexOf( single_char, last_location ) + 1 )
        {
            total = total + 1;
        }
        return total;
    };

これは、カウンター、長いvar名、および1 varの誤用のために遅くなります。

それを使うためには、これをするだけです:

    'The char "a" only shows up twice'.timesCharExist('a');

編集:(2013/12/16)

Opera 12.16以前では使用しないでください。正規表現のソリューションよりも2.5倍近くかかります。

クロムでは、この解決策は1,000,000文字に対して14msから20msかかります。

正規表現の解法は同じ量で11-14msかかります。

関数の使用(String.prototypeの外側)は約10-13msかかります。

これが使用されるコードです:

    String.prototype.timesCharExist=function(c){var t=0,l=0,c=(c+'')[0];while(l=this.indexOf(c,l)+1)++t;return t};

    var x=Array(100001).join('1234567890');

    console.time('proto');x.timesCharExist('1');console.timeEnd('proto');

    console.time('regex');x.match(/1/g).length;console.timeEnd('regex');

    var timesCharExist=function(x,c){var t=0,l=0,c=(c+'')[0];while(l=x.indexOf(c,l)+1)++t;return t;};

    console.time('func');timesCharExist(x,'1');console.timeEnd('func');

すべての解決策の結果は100,000になるはずです。

注:この関数に複数のcharをカウントさせたい場合は、is c=(c+'')[0]c=c+''に変更してください。

8
Ismael Miguel
String.prototype.Count = function (find) {
    return this.split(find).length - 1;
}

console.log("This is a string.".Count("is"));

これは2を返します。

7
Fad Seck
var temp = "This is a string.";
console.log((temp.match(new RegExp("is", "g")) || []).length);
7
Sunil Garg

正規表現の目的はindexOfとはかなり異なると思います。 indexOf正規表現では[A-Z]のようなワイルドカードを使うことができますが、実際の文字を使わずに any /の大文字を見つけることができます。

例:

 var index = "This is a string".indexOf("is");
 console.log(index);
 var length = "This is a string".match(/[a-z]/g).length;
 // where [a-z] is a regex wildcard expression thats why its slower
 console.log(length);
4
Simm
       var myString = "This is a string.";
        var foundAtPosition = 0;
        var Count = 0;
        while (foundAtPosition != -1)
        {
            foundAtPosition = myString.indexOf("is",foundAtPosition);
            if (foundAtPosition != -1)
            {
                Count++;
                foundAtPosition++;
            }
        }
        document.write("There are " + Count + " occurrences of the Word IS");

参照してください: - 文字列に現れる部分文字列を数える ステップバイステップの説明。

3
Ranju
function get_occurrence(varS,string){//Find All Occurrences
        c=(string.split(varS).length - 1);
        return c;
    }
    temp="This is a string.";
    console.log("Total Occurrence is "+get_occurrence("is",temp));

String内の文字と文字列の両方の出現を見つけるには、get_occurrence(varS、string)を使用します。

3
Rahul Ranjan

すごく古いですが、今日このようなことをする必要があり、その後SOをチェックすることだけを考えました。私にとってはかなり速いです。

String.prototype.count = function(substr,start,overlap) {
    overlap = overlap || false;
    start = start || 0;

    var count = 0, 
        offset = overlap ? 1 : substr.length;

    while((start = this.indexOf(substr, start) + offset) !== (offset - 1))
        ++count;
    return count;
};
3
Jason Larke

将来このスレッドを見つけた人のために、$.のような正規表現演算子を詰めるので、一般化しても受け入れられた答えが必ずしも正しい値を返すとは限らないことに注意してください。これは any needleを処理できるより良いバージョンです。

function occurrences (haystack, needle) {
  var _needle = needle
    .replace(/\[/g, '\\[')
    .replace(/\]/g, '\\]')
  return (
    haystack.match(new RegExp('[' + _needle + ']', 'g')) || []
  ).length
}
3
bcherny

上記の@ Vittim.usの回答を基にしています。私は彼の方法が私に与えるコントロールを好きで、それを拡張するのを簡単にします、しかし、私は大文字小文字を区別しないで、句読点のサポートで全単語にマッチを制限する必要がありました。 (例:「お風呂」は「入浴」ですが、「入浴」はできません)

https://stackoverflow.com/a/25575009/497745regexを使用してJavaScriptで文字列からすべての句読点を削除する方法は?

function keywordOccurrences(string, subString, allowOverlapping, caseInsensitive, wholeWord)
{

    string += "";
    subString += "";
    if (subString.length <= 0) return (string.length + 1); //deal with empty strings

    if(caseInsensitive)
    {            
        string = string.toLowerCase();
        subString = subString.toLowerCase();
    }

    var n = 0,
        pos = 0,
        step = allowOverlapping ? 1 : subString.length,
        stringLength = string.length,
        subStringLength = subString.length;

    while (true)
    {
        pos = string.indexOf(subString, pos);
        if (pos >= 0)
        {
            var matchPos = pos;
            pos += step; //slide forward the position pointer no matter what

            if(wholeWord) //only whole Word matches are desired
            {
                if(matchPos > 0) //if the string is not at the very beginning we need to check if the previous character is whitespace
                {                        
                    if(!/[\s\u2000-\u206F\u2E00-\u2E7F\\'!"#$%&\(\)*+,\-.\/:;<=>[email protected]\[\]^_`{|}~]/.test(string[matchPos - 1])) //ignore punctuation
                    {
                        continue; //then this is not a match
                    }
                }

                var matchEnd = matchPos + subStringLength;
                if(matchEnd < stringLength - 1)
                {                        
                    if (!/[\s\u2000-\u206F\u2E00-\u2E7F\\'!"#$%&\(\)*+,\-.\/:;<=>[email protected]\[\]^_`{|}~]/.test(string[matchEnd])) //ignore punctuation
                    {
                        continue; //then this is not a match
                    }
                }
            }

            ++n;                
        } else break;
    }
    return n;
}

バグや改善点を見つけた場合は、この回答を自由に修正してください。

3
Ayo I

それを試してみてください

<?php 
$str = "33,33,56,89,56,56";
echo substr_count($str, '56');
?>

<script type="text/javascript">
var temp = "33,33,56,89,56,56";
var count = temp.match(/56/g);  
alert(count.length);
</script>
2
The Clouds

正規表現なしのシンプルバージョン:

var temp = "This is a string.";

var count = (temp.split('is').length - 1);

alert(count);
2
Jorge Alberto

今、これは私が遭遇した非常に古いスレッドです、しかし、多くが彼らの答えを押したので、ここにこの単純なコードで誰かを助けることを望んでいる私のものがあります。

var search_value = "This is a dummy sentence!";
var letter = 'a'; /*Can take any letter, have put in a var if anyone wants to use this variable dynamically*/
letter = letter[letter.length - 1];
var count;
for (var i = count = 0; i < search_value.length; count += (search_value[i++] == letter));
console.log(count);

私がそれが最速の解決策であるかどうか私にはわからないが、私は単純さと正規表現を使わないことのためにそれを好んだ(私はただそれらを使うのが好きではない!)

2
Tushar Shukla

誰もこれを見ることはありませんが、時々再帰と矢印の機能を元に戻すのは良いことです(素晴らしいことを意図しています)。

String.prototype.occurrencesOf = function(s, i) {
 return (n => (n === -1) ? 0 : 1 + this.occurrencesOf(s, n + 1))(this.indexOf(s, (i || 0)));
};
1
BaseZen

Leandro Batistaへの回答:正規表現の問題です。

 "use strict";
 var dataFromDB = "testal";
 
  $('input[name="tbInput"]').on("change",function(){
        var charToTest = $(this).val();
        var howManyChars = charToTest.length;
        var nrMatches = 0;
        if(howManyChars !== 0){
                charToTest = charToTest.charAt(0);
                var regexp = new RegExp(charToTest,'gi');
                var arrMatches = dataFromDB.match(regexp);
                nrMatches = arrMatches ? arrMatches.length : 0;
        }
                $('#result').html(nrMatches.toString());

  });
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="main">
What do you wanna count <input type="text" name="tbInput" value=""><br />
Number of occurences = <span id="result">0</span>
</div>
0
PhilMaGeo

この投稿に出くわした。

let str = 'As sly as a fox, as strong as an ox';

let target = 'as'; // let's look for it

let pos = 0;
while (true) {
  let foundPos = str.indexOf(target, pos);
  if (foundPos == -1) break;

  alert( `Found at ${foundPos}` );
  pos = foundPos + 1; // continue the search from the next position
}

同じアルゴリズムをより短くレイアウトできます:

let str = "As sly as a fox, as strong as an ox";
let target = "as";

let pos = -1;
while ((pos = str.indexOf(target, pos + 1)) != -1) {
  alert( pos );
}
0
Ashok R

この解決策は、最初のパラメータとしてRegExを、2番目のパラメータとして 関数を受け取る.replace()メソッドに基づいています これは、カウンタを増分するクロージャとして使用することができます...

/**
 * Return the frequency of a substring in a string
 * @param {string} string - The string.
 * @param {string} string - The substring to count.
 * @returns {number} number - The frequency.
 * 
 * @author Drozerah https://Gist.github.com/Drozerah/2b8e08d28413d66c3e63d7fce80994ce
 * @see https://stackoverflow.com/a/55670859/9370788
 */
const subStringCounter = (string, subString) => {

    let count = 0
    string.replace(new RegExp(subString, 'gi'), () => count++)
    return count
}

使用法

subStringCounter("foofoofoo", "bar"); //0

subStringCounter("foofoofoo", "foo"); //3
0
Drozerah

少し遅れましたが、次のような文字列があるとします。

var temp = "This is a string.";

最初に私達はあなたがマッチさせようとしているものは何でもに分割します、これは文字列の配列を返します。

var array = temp.split("is");

Splitはデフォルトでサイズ1の配列になり、結果として出現が見つかるたびにそのサイズが増加するため、その長さを求めて1を引きます。

var occurrenceCount = array.length - 1;
alert(occurrenceCount); //should output '2'

次のように、これらすべてを1行で実行することもできます。

alert("This is a string.".split("is").length - 1); //should output '2'

それが役立つことを願っています:D

var s = "1";replaced Word
var a = "HRA"; //have to replace 
var str = document.getElementById("test").innerHTML;
var count = str.split(a).length - 1;
for (var i = 0; i < count; i++) {
    var s = "1";
    var a = "HRA";
    var str = document.getElementById("test").innerHTML;
    var res = str.replace(a, s);
    document.getElementById("test").innerHTML = res;
}
<input " type="button" id="Btn_Validate" value="Validate" class="btn btn-info" />
<div class="textarea"  id="test" contenteditable="true">HRABHRA</div>
0
jithin
var countInstances = function(body, target) {
  var globalcounter = 0;
  var concatstring  = '';
  for(var i=0,j=target.length;i<body.length;i++){
    concatstring = body.substring(i-1,j);
    
    if(concatstring === target){
       globalcounter += 1;
       concatstring = '';
    }
  }
  
  
  return globalcounter;
 
};

console.log(   countInstances('abcabc', 'abc')   ); // ==> 2
console.log(   countInstances('ababa', 'aba')   ); // ==> 2
console.log(   countInstances('aaabbb', 'ab')   ); // ==> 1
0
Kamal