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.
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
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.
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:)
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
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
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.
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
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;
}
}
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
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.
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");
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
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 virgulemainStr.split(',').length - 1
// donne 3, qui est le nombre de virgule
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.
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
s = 'dir/dir/dir/dir/'
for(i=l=0;i<s.length;i++)
if(s[i] == '/')
l++
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;
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;
}
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++;
}
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!
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.");
}
Ma solution:
function countOcurrences(str, value){
var regExp = new RegExp(value, "gi");
return str.match(regExp) ? str.match(regExp).length : 0;
}
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
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;
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;
}
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.
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
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.
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);
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");