Comment compter l'occurrence de chaîne en chaîne?

Comment puis-je compter le nombre de fois qu'une chaîne particulière se produit dans une autre chaîne. Par exemple, c'est ce que j'essaie de faire en Javascript:

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

Le g dans l'expression régulière (court pour le monde ) dit de rechercher toute la chaîne plutôt que de trouver la première occurrence:

 var temp = "This is a string."; var count = (temp.match(/is/g) || []).length; console.log(count); 
 /** 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; } 

Usage

 occurrences("foofoofoo", "bar"); //0 occurrences("foofoofoo", "foo"); //3 occurrences("foofoofoo", "foofoo"); //1 

AllowOverlapping

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

Allumettes:

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

Test de l'unité

Référence

J'ai fait un test de référence et ma fonction est plus de 10 fois plus rapide que la fonction de correspondance regexp publiée par gumbo. Dans ma chaîne de test est de 25 caractères de longueur. Avec 2 occurrences du personnage 'o'. J'ai exécuté 1 000 000 fois dans Safari.

Safari 5.1

Indice de référence> Exécution du temps total: 5617 ms (regexp)

Indice de référence> Exécution du temps total: 881 ms (ma fonction 6,4 fois plus rapide)

Firefox 4

Indice de référence> Exécution du temps total: 8547 ms (Rexexp)

Indice de référence> Exécution du temps total: 634 ms (ma fonction 13,5 fois plus rapide)


Modifier: modifications que j'ai faites

  • Longueur cachée en sous-chaîne

  • Ajout de type-casting à string.

  • Paramètre optionnel 'allowOverlapping' optionnel

  • Correction de la sortie correcte pour le "" encadré vide ".

Essentiel

 function countInstances(string, word) { var substrings = string.split(word); return substrings.length - 1; } 

Vous pouvez essayer ceci:

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

Ma solution:

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

Vous pouvez utiliser la match pour définir cette fonction:

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

Juste le code-golf de la solution ci-dessus 🙂

alert("This is a string." + match(/is/g).length);

Voici la fonction la plus rapide!

Pourquoi est-il plus rapide?

  • Ne vérifie pas char par char (avec 1 exception)
  • Utilise un certain temps et augmente 1 var (le nombre de caractères var) par rapport à une boucle pour vérifier la longueur et incrémenter 2 vars (généralement var i et un var avec le nombre de caractères)
  • Utilise WAY moins de vars
  • N'utilise pas regex!
  • Utilise une fonction (optimiste) hautement optimisée
  • Toutes les opérations sont aussi combinées qu'elles peuvent être, en évitant les ralentissements dus à des opérations multiples

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

Voici une version plus lente et lisible:

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

Celui-ci est plus lent en raison du compteur, de longs noms var et de mauvaise utilisation de 1 var.

Pour l'utiliser, il suffit de faire ceci:

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

Modifier: (2013/12/16)

N'utilisez PAS avec Opera 12.16 ou plus! Il faudra presque 2,5 fois plus que la solution regex!

Sur chrome, cette solution prend entre 14 ms et 20 ms pour 1 000 000 de caractères.

La solution regex prend 11 à 14 ms pour le même montant.

L'utilisation d'une fonction (en dehors de String.prototype ) prendra environ 10 à 13 ms.

Voici le code utilisé:

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

Le résultat de toutes les solutions devrait être de 100 000!

Remarque: si vous voulez que cette fonction compte plus de 1 char, modifiez où est c=(c+'')[0] dans c=c+''

La version non-regex:

  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 
 var temp = "This is a string."; console.log((temp.match(new RegExp("is", "g")) || []).length); 

Je pense que le but de regex est très différent de l' indexOf . indexOf trouver simplement l'occurrence d'une certaine chaîne alors que dans regex, vous pouvez utiliser des caractères génériques comme [AZ] ce qui signifie qu'il trouvera un caractère capital dans le mot sans indiquer le caractère réel.

Exemple:

  var index = "This is a string".indexOf("is"); console.log(index); var length = "This is a string".match(/[az]/g).length; // where [az] is a regex wildcard expression thats why its slower console.log(length); 

Super duper vieux, mais j'avais besoin de faire quelque chose comme ça aujourd'hui et je pensais seulement vérifier SO après. Fonctionne assez vite pour moi.

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

Référer: – compter une sous-chaîne apparaît dans la chaîne pour l'explication étape par étape.

S'appuyant sur la réponse @ Vittim.us ci-dessus. J'aime le contrôle que me donne sa méthode, ce qui facilite l'extension, mais j'ai dû ajouter une insensibilité à la casse et limiter les allumettes à des mots entiers avec le soutien de la ponctuation. (Par exemple, "bain" est "prendre un bain", mais pas "se baigner")

La regex de ponctuation provient de: https://stackoverflow.com/a/25575009/497745 ( Comment puis-je supprimer la ponctuation d'une chaîne dans JavaScript en utilisant regex? )

 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\\'!"#$%&\(\)*+,\-.\/:;<=>?@\[\]^_`{|}~]/.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\\'!"#$%&\(\)*+,\-.\/:;<=>?@\[\]^_`{|}~]/.test(string[matchEnd])) //ignore punctuation { continue; //then this is not a match } } } ++n; } else break; } return n; } 

N'hésitez pas à modifier et à refacher cette réponse si vous détectez des problèmes ou des améliorations.

String.prototype.Count = function (find) { return this.split(find).length - 1; } "This is a string.".Count("is");

Cela renverra 2.

Pour quiconque trouve ce fil à l'avenir, notez que la réponse acceptée ne renverra pas toujours la valeur correcte si vous la généralisez, car elle va étouffer sur les opérateurs Regex comme $ et . . Voici une meilleure version, qui peut gérer n'importe quelle aiguille:

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

Essayez-le

 <?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> 

Version simple sans regex:

 var temp = "This is a string."; var count = (temp.split('is').length - 1); alert(count); 

Maintenant, c'est un très vieux fil que j'ai rencontré, mais tant ont poussé leur réponse, voici le mien dans l'espoir d'aider quelqu'un avec ce code simple.

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

Essaye ça:

 function countString(str, search){ var count=0; var index=str.indexOf(search); while(index!=-1){ count++; index=str.indexOf(search,index+1); } return count; }