Je dois compter le nombre d'occurrences d'un caractère dans une chaîne.
Par exemple, supposons que ma chaîne contienne:
var mainStr = "str1,str2,str3,str4";
Je veux trouver le nombre de virgules ,
, qui est 3. Et le nombre de chaînes individuelles après la division par virgule, qui est 4.
Je dois également valider que chacune des chaînes, à savoir str1, str2, str3 ou str4, ne doit pas dépasser 15 caractères.
J'ai mis à jour cette réponse. J'aime mieux l'idée d'utiliser un match, 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 auparavant. Sinon, vous pouvez utiliser le constructeur RegExp
et transmettre l'indicateur g
en tant qu'argument.
match
renvoie null
sans résultat, ainsi le || []
La réponse originale que j'ai faite en 2009 est ci-dessous. Cela crée un tableau inutilement, mais utiliser une scission est plus rapide (à partir de septembre 2014). Je suis ambivalent, si j'avais vraiment besoin de la vitesse, il ne ferait aucun doute que j'utiliserais un split, mais je préférerais utiliser le match.
Ancienne réponse (à partir de 2009):
Si vous recherchez 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 test de jsperf idiot, le fractionnement avance rapidement, du moins sous Chrome, mais créer de nouveau le tableau supplémentaire ne semble tout simplement pas sain d'esprit.
Il y a au moins quatre façons. La meilleure option, qui devrait également être la plus rapide (avec le moteur RegEx natif), est placée en haut. jsperf.com est actuellement en panne, sinon je vous fournirais des statistiques de performance.
Update: Veuillez trouver les tests de performance ici et les exécuter vous-mêmes, de manière à contribuer à vos résultats. Les détails des résultats seront donnés plus tard.
("this is foo bar".match(/o/g)||[]).length
//>2
"this is foo bar".split("o").length-1
//>2
split non recommandé. Ressources affamées. Alloue de nouvelles instances de 'Array' pour chaque match. N'essayez pas cela pour un fichier> 100 Mo via FileReader. En fait, vous pouvez facilement observer l'utilisation des ressources EXACT à l'aide de l'option profileur de 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
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
Mettre à jour:
la cartographie et le filtrage des éléments, non recommandés en raison de la préallocation globale de leurs ressources plutôt que de l'utilisation de «générateurs» Pythonian
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
(Share:} _ J'ai créé ceci Gist, avec actuellement 8 méthodes de décompte des caractères, afin que nous puissions partager et partager nos idées directement - pour le plaisir, et peut-être même quelques-unes repères intéressants :)
Ajoutez 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;
};
usage:
console.log("strings".count("s")); //2
Un rapide Google search 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 constaté que la meilleure approche pour rechercher un caractère dans une très grande chaîne (1 000 000 caractères, par exemple) consiste à utiliser la méthode replace()
.
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 ainsi que d’autres méthodes de recherche d’un caractère dans une chaîne.
ok, un autre avec regexp - probablement pas rapide, mais plus lisible que d’autres, dans mon cas, '_'
compter
key.replace(/[^_]/g,'').length
supprimez simplement tout ce qui ne ressemble pas à votre personnage mais il ne semble pas agréable avec une chaîne en tant qu'entrée
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");
J'ai apporté une légère amélioration à la réponse acceptée, cela permet de vérifier avec une correspondance sensible à la casse/insensible à la casse et constitue une méthode attachée à l'objet chaîne:
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 (telle que 'ex'), et cis est insensible à la casse, par défaut à false, il permettra le choix de correspondances insensibles à la casse .
'I love StackOverflow.com'
la lettre minuscule 'o'
, vous devez utiliser:var amount_of_os = 'I love StackOverflow.com'.count('o');
amount_of_os
serait égal à 2
.
var amount_of_os = 'I love StackOverflow.com'.count('o', true);
Cette fois, amount_of_os
serait égal à 3
, car la majuscule O
de la chaîne est incluse dans la recherche.
Je travaillais sur un petit projet nécessitant un compteur de sous-chaînes. La recherche des mauvaises phrases ne m'a donné aucun résultat. Cependant, après avoir écrit ma propre implémentation, je suis tombé sur cette question. Quoi qu'il en soit, voici mon chemin, il est probablement plus lent que la plupart des gens 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;
}
}
S'il vous plaît laissez-moi savoir si vous trouvez cette mise en œuvre à échouer ou ne pas suivre certaines normes! :)
UPDATE Vous voudrez peut-être remplacer:
for (var i = 0; i < input.length; i++) {
Avec:
for (var i = 0, input_length = input.length; i < input_length; i++) {
Intéressant lu en discutant de ce qui précède: http://www.erichynds.com/blog/javascript-length-property-is-a-stored-value
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 cela a été mentionné, la division est beaucoup plus rapide que le remplacement.
Le 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
Si vous utilisez lodash, la méthode _.countBy fera ceci:
_.countBy("abcda")['a'] //2
Cette méthode fonctionne aussi avec array:
_.countBy(['ab', 'cd', 'ab'])['ab'] //2
J'utilise Node.js v.6.0.0 et le plus rapide est celui avec index (la troisième méthode dans la réponse de Lo Sauer).
La seconde est:
function count(s, c) {
var n = 0;
for (let x of s) {
if (x == c)
n++;
}
return n;
}
Qu'en est-il de string.split (Caractère souhaité) .length-1
Exemple:
var str = "bonjour comment va la vie"; var len = str.split ("h"). length-1; donnera le compte 2 pour le caractère "h" dans la chaîne ci-dessus;
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, ou plus, sans virgule. S'il réussit le test, il divise ensuite la chaîne. compter les virgules est aussi simple que 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.");
}
Vous pouvez également reposer votre chaîne et la manipuler comme un tableau d’éléments 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);
Voici une méthode presque aussi rapide que les méthodes split et replace, qui sont un peu plus rapides que la méthode regex (en chrome).
var num = 0;
for (ch of "str1,str2,str3,str4")
{
if (ch === ',') num++;
}
s = 'dir/dir/dir/dir/'
for(i=l=0;i<s.length;i++)
if(s[i] == '/')
l++
Et voici:
function character_count(string, char, ptr = 0, count = 0) {
while (ptr = string.indexOf(char, ptr) + 1) {count ++}
return count
}
Fonctionne aussi avec des nombres entiers!
Ma solution:
function countOcurrences(str, value){
var regExp = new RegExp(value, "gi");
return str.match(regExp) ? str.match(regExp).length : 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);
En javascript, vous pouvez utiliser le code ci-dessus pour obtenir l'occurrence d'un caractère dans une chaîne.
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 comparer chaque caractère par rapport à un autre caractère de la chaîne, en incrémentant une variable count pour chaque. personnage trouvé qui est égal à ce personnage.
J'ai créé un nouvel objet vierge dans lequel chaque clé de propriété est un caractère et la valeur correspond au nombre de fois que chaque caractère est apparu dans la chaîne (nombre).
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;
}
La fonction prend string str comme paramètre et compte l'occurrence de chaque caractère unique dans la chaîne. Le résultat est présenté par paire clé/valeur pour chaque caractère.
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;
}
Je viens de faire un test très rapide et sale sur repl.it en utilisant Node v7.4. Pour un seul caractère, la norme pour la boucle est la plus rapide:
Quelques 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 essais:
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 de la réponse Leo Sauers échoue si le caractère se trouve au début de la chaîne .
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 filtrage Boolean donne false pour 0.
Autre fonction de filtrage possible:
haystack.split('').map(function (e, i) {
if (e === needle) return i;
}).filter(function (item) {
return !isNaN(item);
}).length;
Voici ma solution. Beaucoup de solutions déjà postées devant moi. Mais j'aime partager mon point de vue ici.
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
Ma solution avec ramda js:
const testString = 'somestringtotest'
const countLetters = R.compose(
R.map(R.length),
R.groupBy(R.identity),
R.split('')
)
countLetters(testString)
Je pense que vous trouverez la solution ci-dessous très courte, très rapide, capable de travailler avec de très longues chaînes, capable de supporter plusieurs recherches de caractères, de vérifier les erreurs et de gérer des 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 principal bogue de performance de Jakub Wawszczyk, selon lequel le code cherche toujours une correspondance, même après que indexOf a déclaré qu'il n'en existait aucune et que sa version elle-même ne fonctionnait pas, car il avait oublié de donner les paramètres d'entrée de la fonction.
La méthode la plus rapide semble être via l'opérateur d'index:
function charOccurances (str, char)
{
for (var c = 0, i = 0, len = str.length; i < len; ++i)
{
if (str[i] == char)
{
++c;
}
}
return c;
}
Usage:
charOccurances('example/path/script.js', '/') == 2
Ou en tant que 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;
}
Usage:
charOccurances('example/path/script.js', '/') == 2