Compter le nombre de correspondances d'une regex en Javascript
98
Je voulais écrire une regex pour compter le nombre d'espaces / tabulations / nouvelle ligne dans un morceau de texte. J'ai donc écrit naïvement ce qui suit: -
Pour des raisons inconnues, il revient toujours 1. Quel est le problème avec la déclaration ci-dessus? Depuis, j'ai résolu le problème avec ce qui suit: -
// THIS IS WHAT YOU NEEDconst count =(str)=>{const re =/YOUR_PATTERN_HERE/g
return((str ||'').match(re)||[]).length
}
Pour ceux qui sont arrivés ici à la recherche d'un moyen générique de compter le nombre d'occurrences d'un modèle regex dans une chaîne, et ne veulent pas qu'il échoue s'il n'y a aucune occurrence, ce code est ce dont vous avez besoin. Voici une démonstration:
/*
* Example
*/const count =(str)=>{const re =/[a-z]{3}/g
return((str ||'').match(re)||[]).length
}const str1 ='abc, def, ghi'const str2 ='ABC, DEF, GHI'
console.log(`'${str1}' has ${count(str1)} occurrences of pattern '/[a-z]{3}/g'`)
console.log(`'${str2}' has ${count(str2)} occurrences of pattern '/[a-z]{3}/g'`)
Cela fonctionne tant que vous avez au moins un espace dans votre entrée. Sinon, match () retourne de manière ennuyeuse null.
sfink
3
sfink a raison, vous voulez certainement vérifier si match () a renvoyé null:var result = text.match(/\s/g); return result ? result.length : 0;
Gras Double
37
Vous pouvez également vous protéger contre le nul en utilisant cette construction:( str.match(...) || [] ).length
a'r
11
Comme mentionné dans ma réponse précédente , vous pouvez utiliser RegExp.exec()pour parcourir toutes les correspondances et compter chaque occurrence; l'avantage est limité à la mémoire uniquement, car dans l'ensemble, c'est environ 20% plus lent que l'utilisation String.match().
var re =/\s/g,
count =0;while(re.exec(text)!==null){++count;}return count;
Je pense que vous avez mis le || []mauvais endroit, ça devrait être('my string'.match(/\s/g) || []).length
woojoo666
0
C'est certainement quelque chose qui a beaucoup de pièges. Je travaillais avec la réponse de Paolo Bergantino et je me rendais compte que même cela a des limites. J'ai trouvé que travailler avec des représentations sous forme de chaîne de dates était un bon endroit pour trouver rapidement certains des principaux problèmes. Commencez par une chaîne d'entrée comme celle-ci:
'12-2-2019 5:1:48.670'
et configurez la fonction de Paolo comme ceci:
function count(re, str){if(typeof re !=="string"){return0;}
re =(re ==='.')?('\\'+ re): re;var cre =newRegExp(re,'g');return((str ||'').match(cre)||[]).length;}
Je voulais que l'expression régulière soit transmise, afin que la fonction soit plus réutilisable, deuxièmement, je voulais que le paramètre soit une chaîne, afin que le client n'ait pas à créer l'expression régulière, mais simplement correspondre à la chaîne, comme une méthode de classe utilitaire de chaîne standard.
Maintenant, vous pouvez voir ici que je traite des problèmes avec l'entrée. Avec ce qui suit:
if(typeof re !=="string"){return0;}
Je me assure que l'entrée est rien comme le littéral 0, false, undefinedou null, dont aucun ne sont des chaînes. Étant donné que ces littéraux ne sont pas dans la chaîne d'entrée, il ne devrait y avoir aucune correspondance, mais cela devrait correspondre '0', qui est une chaîne.
Avec ce qui suit:
re =(re ==='.')?('\\'+ re): re;
Je traite du fait que le constructeur RegExp interprètera (je pense, à tort) la chaîne '.'comme la correspondance de tous les caractères\.\
Enfin, parce que j'utilise le constructeur RegExp, je dois lui donner le 'g'drapeau global pour qu'il compte toutes les correspondances, pas seulement la première, similaire aux suggestions d'autres articles.
Je me rends compte que c'est une réponse extrêmement tardive, mais cela pourrait être utile à quelqu'un qui trébuche ici. BTW voici la version TypeScript:
function count(re: string, str: string): number {if(typeof re !=='string'){return0;}
re =(re ==='.')?('\\'+ re): re;const cre =newRegExp(re,'g');return((str ||'').match(cre)||[]).length;}
var result = text.match(/\s/g); return result ? result.length : 0;
( str.match(...) || [] ).length
Comme mentionné dans ma réponse précédente , vous pouvez utiliser
RegExp.exec()
pour parcourir toutes les correspondances et compter chaque occurrence; l'avantage est limité à la mémoire uniquement, car dans l'ensemble, c'est environ 20% plus lent que l'utilisationString.match()
.la source
Basé sur https://stackoverflow.com/a/48195124/16777 mais corrigé pour fonctionner réellement dans le cas de zéro résultat.
la source
('my string'.match(/\s/g) || []).length;
la source
|| []
mauvais endroit, ça devrait être('my string'.match(/\s/g) || []).length
C'est certainement quelque chose qui a beaucoup de pièges. Je travaillais avec la réponse de Paolo Bergantino et je me rendais compte que même cela a des limites. J'ai trouvé que travailler avec des représentations sous forme de chaîne de dates était un bon endroit pour trouver rapidement certains des principaux problèmes. Commencez par une chaîne d'entrée comme celle-ci:
'12-2-2019 5:1:48.670'
et configurez la fonction de Paolo comme ceci:
Je voulais que l'expression régulière soit transmise, afin que la fonction soit plus réutilisable, deuxièmement, je voulais que le paramètre soit une chaîne, afin que le client n'ait pas à créer l'expression régulière, mais simplement correspondre à la chaîne, comme une méthode de classe utilitaire de chaîne standard.
Maintenant, vous pouvez voir ici que je traite des problèmes avec l'entrée. Avec ce qui suit:
Je me assure que l'entrée est rien comme le littéral
0
,false
,undefined
ounull
, dont aucun ne sont des chaînes. Étant donné que ces littéraux ne sont pas dans la chaîne d'entrée, il ne devrait y avoir aucune correspondance, mais cela devrait correspondre'0'
, qui est une chaîne.Avec ce qui suit:
Je traite du fait que le constructeur RegExp interprètera (je pense, à tort) la chaîne
'.'
comme la correspondance de tous les caractères\.\
Enfin, parce que j'utilise le constructeur RegExp, je dois lui donner le
'g'
drapeau global pour qu'il compte toutes les correspondances, pas seulement la première, similaire aux suggestions d'autres articles.Je me rends compte que c'est une réponse extrêmement tardive, mais cela pourrait être utile à quelqu'un qui trébuche ici. BTW voici la version TypeScript:
la source
et comme ça
la source