Compter le nombre d'occurrences d'un caractère dans une chaîne en Javascript

J'ai besoin de compter le nombre d'occurrences d'un caractère dans une chaîne.

Par exemple, supposons que ma chaîne contient:

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

Je veux trouver le nombre de virgule , caractère, qui est 3. Et le nombre de chaînes individuelles après la division le long de la virgule, Qui est 4.

J'ai aussi besoin de valider que chacune des chaînes.e ch1 ou ch2 ou str3 ou str4 ne doit pas dépasser, disons, 15 caractères.

374
demandé sur Cœur 2009-05-19 09:24:24

28 réponses

J'ai mis à jour cette réponse. J'aime l'idée d'utiliser un match mieux, mais c'est plus lent:

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

Utilisez un littéral d'expression régulière si vous savez ce que vous recherchez à l'avance, sinon vous pouvez utiliser le constructeur RegExp et passer l'indicateur g comme argument.

match renvoie null sans résultat donc le || []

La réponse originale que j'ai faite en 2009 est ci-dessous. Il crée un tableau inutilement, mais en utilisant un split est plus rapide (à partir de septembre 2014). Je suis ambivalent, si j'avais vraiment besoin de la vitesse, il ne fait aucun doute que j'utiliserais un split, mais je préférerais utiliser match.

Ancienne réponse (de 2009):

Si vous cherchez les virgules:

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

Si vous cherchez le str

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

À la fois dans la réponse de @Lo et dans mon propre stupide jsperf test split arrive en avance en vitesse, au moins dans Chrome, mais encore une fois créer le tableau supplémentaire ne semble pas sain d'esprit.

563
répondu Bjorn Tipling 2014-09-08 20:41:12

Il y a au moins quatre façons. La meilleure option, qui devrait également être la plus rapide-en raison du moteur RegEx natif -, est placée en haut. jsperf.com est actuellement en baisse, sinon je vous fournirais des statistiques de performance.

mise à Jour: Veuillez trouver les tests de performance ici, et de les exécuter vous-mêmes, afin de contribuer vos résultats. Les détails des résultats seront donnés tard.

1.

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

2.

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

Split non recommandé. Gourmandes en ressources. Alloue de nouvelles instances de 'Array' pour chaque correspondance. N'essayez pas cela pour un fichier > 100MB via FileReader. Vous pouvez facilement observer L'utilisation exacte des ressources en utilisant l'optionProfiler de Chrome .

3.

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.

Recherche d'un seul caractère

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

Mise à Jour:

5.

Mappage et filtrage des éléments, non recommandés en raison de sa préallocation globale des ressources plutôt que d'utiliser des 'générateurs' Pythoniens

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

Partager: J'ai fait ça gist, avec actuellement 8 méthodes de comptage de caractères, Nous pouvons donc mettre en commun et partager directement nos idées-juste pour le plaisir, et peut-être quelques repères intéressants:)

Https://gist.github.com/2757250

167
répondu Lorenz Lo Sauer 2013-11-24 20:11:47

Ajouter cette fonction au prototype sting:

String.prototype.count=function(c) { 
  var result = 0, i = 0;
  for(i;i<this.length;i++)if(this[i]==c)result++;
  return result;
};

Utilisation:

console.log("strings".count("s")); //2
14
répondu Philippe Boissonneault 2015-01-08 18:15:00

Une recherche rapide Google a obtenu ceci (de 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;
}

Utilisez-le comme ceci:

test = 'one,two,three,four'
commas = test.count(',') // returns 3
8
répondu immibis 2009-05-19 05:54:12

J'ai trouvé que la meilleure approche pour rechercher un caractère dans une très grande chaîne (qui est de 1 000 000 de caractères, par exemple) est d'utiliser le replace() méthode.

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

Vous pouvez voir encore une autre suite jsperf pour tester cette méthode avec d'autres méthodes de recherche d'un caractère dans une chaîne.

4
répondu Valera Rozuvan 2014-05-07 16:07:45

Ok, un autre avec regexp-probablement pas rapide , mais court et mieux lisible que d'autres, dans mon cas juste '_' pour compter

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

Il suffit de supprimer tout ce qui ne ressemble pas à votre char mais ça n'a pas l'air bien avec une chaîne en entrée

4
répondu halfbit 2015-07-15 20:10:32

Je travaillais sur un petit projet qui nécessitait un compteur de sous-chaînes. La recherche des mauvaises phrases ne m'a fourni aucun résultat, mais après avoir écrit ma propre implémentation, j'ai trébuché sur cette question. Quoi qu'il en soit, voici mon chemin, il est probablement plus lent que la plupart ici mais pourrait être utile à quelqu'un:

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/

Veuillez me faire savoir si vous trouvez que cette implémentation échoue ou ne respecte pas certaines normes! :)

Mise à jour Vous pouvez remplacer:

    for (var i = 0; i < input.length; i++) {

Avec:

for (var i = 0, input_length = input.length; i < input_length; i++) {

Intéressant lire discuter de ce qui précède: http://www.erichynds.com/blog/javascript-length-property-is-a-stored-value

3
répondu Jakub Wawszczyk 2014-10-14 11:52:14

J'ai fait une légère amélioration sur la réponse acceptée, elle permet de vérifier avec une correspondance sensible à la casse/insensible à la casse, et est une méthode attachée à l'objet string:

String.prototype.count = function(lit, cis) {
    var m = this.toString().match(new RegExp(lit, ((cis) ? "gi" : "g")));
    return (m != null) ? m.length : 0;
}

lit est la chaîne à rechercher ( comme 'ex' ), et cis est insensibilité à la casse, par défaut à false, il permettra le choix des correspondances insensibles à la casse.


Pour rechercher la chaîne 'I love StackOverflow.com' pour la lettre minuscule 'o', vous devez utiliser:
var amount_of_os = 'I love StackOverflow.com'.count('o');

amount_of_os serait égale à 2.


Si nous devions rechercher à nouveau la même chaîne en utilisant une correspondance insensible à la casse, vous utiliseriez:
var amount_of_os = 'I love StackOverflow.com'.count('o', true);

Cette fois, {[6] } serait égal à 3, puisque la capitale O de la chaîne est incluse dans la recherche.

3
répondu Dendromaniac 2015-07-11 10:22:05

Performance de 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");
3
répondu Clive Paterson 2016-06-30 08:30:50

Moyen le plus simple que j'ai découvert...

Exemple-

str = 'mississippi';

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

find_occurences(str, 'i') //outputs 4
3
répondu Ankur Choraywal 2017-01-09 11:13:43

Simplement, utiliser le split pour trouver le nombre d'occurrences d'un caractère dans une chaîne.

mainStr.split(',').length // donne 4, qui est le nombre de chaînes après fractionnement à l'aide de séparateur de virgule

mainStr.split(',').length - 1 // donne 3, qui est le nombre de virgule

3
répondu Pranjal Successena 2018-07-13 09:47:35

Voici une solution similaire, mais il utilise réduire

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

Comme il a été mentionné, diviser beaucoup plus vite que remplacer.

2
répondu havenchyk 2016-10-15 22:30:05

Si vous utilisez lodash, le _.la méthode countBy fera ceci:

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

Cette méthode fonctionne également avec array:

_.countBy(['ab', 'cd', 'ab'])['ab'] //2
2
répondu Geng Jiawen 2017-04-06 08:58:47
s = 'dir/dir/dir/dir/'
for(i=l=0;i<s.length;i++)
if(s[i] == '/')
l++
1
répondu wlf 2013-02-22 11:40:15

Qu'en est-il de la chaîne.split(desiredCharecter).longueur-1

Exemple:

Var str = " hellow comment est la vie"; var len = str.split ("h").length-1; donnera le nombre 2 pour le caractère " h " dans la chaîne ci-dessus;

1
répondu user2296195 2016-05-24 08:36:25

J'utilise Node.js v. 6. 0. 0 et le plus rapide est celui avec index (la 3ème méthode dans la réponse de Lo Sauer).

Le second est:

function count(s, c) {
  var n = 0;
  for (let x of s) {
    if (x == c)
      n++;
  }
  return n;
}
1
répondu Marc K. 2016-06-01 23:16:26

En voici un presque aussi rapide que les méthodes split et replace, qui sont un peu plus rapides que la méthode regex (dans chrome).

var num = 0;
for (ch of "str1,str2,str3,str4")
{
    if (ch === ',') num++;
}
1
répondu Gerard ONeill 2017-04-12 20:14:08

Et il y a:

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

Fonctionne aussi avec des entiers!

1
répondu Damion Dooley 2018-07-24 07:51:48

Ce qui suit utilise une expression régulière pour tester la longueur. testex garantit que vous n'avez pas 16 caractères consécutifs Non-virgules ou plus. S'il réussit le test, il procède à la division de la chaîne. compter les virgules est aussi simple que de compter les jetons, moins un.

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.");
}
0
répondu Jonathan Fingland 2009-05-19 06:31:54

Ma solution:

function countOcurrences(str, value){
   var regExp = new RegExp(value, "gi");
   return str.match(regExp) ? str.match(regExp).length : 0;  
}
0
répondu Gere 2013-04-09 01:17:12

Je viens de faire un test très rapide et sale sur repl.it en utilisant le noeud v7. 4. Pour un seul caractère, la norme pour la boucle est la plus rapide:

Certains codes :

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

Résultats de quelques courses :

 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
0
répondu NuSkooler 2017-09-20 03:07:52

La cinquième méthode dans Leo Sauers réponse échoue, si le caractère est au début de la chaîne. par exemple

var needle ='A',
  haystack = 'AbcAbcAbc';

haystack.split('').map( function(e,i){ if(e === needle) return i;} )
  .filter(Boolean).length;

Donnera 2 au lieu de 3, car la fonction de filtre booléen donne false pour 0.

Autre fonction de filtre possible:

haystack.split('').map(function (e, i) {
  if (e === needle) return i;
}).filter(function (item) {
  return !isNaN(item);
}).length;
0
répondu saltimbokka 2017-10-03 15:09:28

Je sais que cela pourrait être une vieille question, mais j'ai une solution simple pour les débutants de bas niveau en JavaScript.

En tant que débutant, Je ne pouvais comprendre que certaines des solutions à cette question, j'ai donc utilisé deux boucles imbriquées pour pour vérifier chaque caractère par rapport à tous les autres caractères de la chaîne, en incrémentant une variablecount pour chaque caractère trouvé qui est égal à ce caractère.

J'ai créé un nouvel objet vide où chaque clé de propriété est un caractère et la valeur est combien de fois chaque caractère est apparu dans la chaîne(count).

Exemple de fonction: -

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
répondu Viscount Wathika 2017-10-17 07:35:41

Je crois que vous trouverez la solution ci-dessous pour être très courte, très rapide, capable de travailler avec des chaînes très longues, capable de prendre en charge plusieurs recherches de caractères, preuve d'erreur, et capable de gérer les recherches de chaînes vides.

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

Exemple d'utilisation:

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

Le code ci-dessus corrige le bug de performance majeur dans Jakub Wawszczyk que le code continue à chercher une correspondance même après que indexOf a dit qu'il n'y en a pas et que sa version elle-même ne fonctionne pas parce qu'il a oublié de donner la fonction des paramètres d'entrée.

0
répondu Jack Giffin 2017-11-24 19:03:48

La méthode La plus rapide semble être via l'index de l'opérateur:

function charOccurances (str, char)
{
    for (var c = 0, i = 0, len = str.length; i < len; ++i)
    {
        if (str[i] == char)
        {
            ++c;
        }
    }
    return c;
}

Utilisation:

charOccurances('example/path/script.js', '/') == 2

Ou comme fonction prototype:

String.prototype.charOccurances = function (char)
{
    for (var c = 0, i = 0, len = this.length; i < len; ++i)
    {
        if (this[i] == char)
        {
            ++c;
        }
    }
    return c;
}

Utilisation:

charOccurances('example/path/script.js', '/') == 2
0
répondu zoran404 2018-01-21 23:12:24
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);

En javascript, vous pouvez utiliser le code ci-dessus pour obtenir l'occurrence d'un caractère dans une chaîne.

0
répondu Nitin Tyagi 2018-03-26 07:32:33

Vous pouvez également rest votre chaîne et travailler avec elle comme un tableau d'éléments en utilisant

const mainStr = 'str1,str2,str3,str4';
const commas = [...mainStr].filter(l => l === ',').length;

console.log(commas);

Ou

const mainStr = 'str1,str2,str3,str4';
const commas = [...mainStr].reduce((a, c) => c === ',' ? ++a : a, 0);

console.log(commas);
0
répondu Yosvel Quintero 2018-08-23 14:10:46

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");
-1
répondu webdev 2018-06-06 09:43:33