tl; dr: Ogólny licznik wzorców
const count = (str) => {
const re = /YOUR_PATTERN_HERE/g
return ((str || '').match(re) || []).length
}
Dla tych, którzy przybyli tutaj i szukają ogólnego sposobu zliczania liczby wystąpień wzorca wyrażenia regularnego w ciągu znaków i nie chcą, aby to się nie powiodło, jeśli wystąpi zero wystąpień, ten kod jest tym, czego potrzebujesz. Oto demonstracja:
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'`)
Oryginalna odpowiedź
Problem z kodem początkowym polega na tym, że brakuje identyfikatora globalnego :
>>> 'hi there how are you'.match(/\s/g).length;
4
Bez g
części wyrażenia regularnego dopasuje tylko pierwsze wystąpienie i na tym zakończy.
Pamiętaj też, że Twoje wyrażenie regularne będzie liczyć kolejne spacje dwukrotnie:
>>> 'hi there'.match(/\s/g).length;
2
Jeśli to nie jest pożądane, możesz zrobić to:
>>> 'hi there'.match(/\s+/g).length;
1
var result = text.match(/\s/g); return result ? result.length : 0;
( str.match(...) || [] ).length
Jak wspomniałem w mojej wcześniejszej odpowiedzi , możesz użyć
RegExp.exec()
do iteracji po wszystkich dopasowaniach i zliczenia każdego wystąpienia; Zaleta ogranicza się tylko do pamięci, ponieważ w sumie jest około 20% wolniejsza niż przy użyciuString.match()
.var re = /\s/g, count = 0; while (re.exec(text) !== null) { ++count; } return count;
źródło
(('a a a').match(/b/g) || []).length; // 0 (('a a a').match(/a/g) || []).length; // 3
Oparty na https://stackoverflow.com/a/48195124/16777, ale naprawiony tak, aby faktycznie działał w przypadku zerowych wyników.
źródło
('my string'.match(/\s/g) || []).length;
źródło
|| []
w złym miejscu, powinno być('my string'.match(/\s/g) || []).length
Jest to z pewnością coś, co ma wiele pułapek. Pracowałem z odpowiedzią Paolo Bergantino i zdałem sobie sprawę, że nawet to ma pewne ograniczenia. Zauważyłem, że praca z reprezentacjami dat w postaci ciągów znaków to dobre miejsce na szybkie znalezienie niektórych głównych problemów. Zacznij od ciągu wejściowego, takiego jak ten:
'12-2-2019 5:1:48.670'
i skonfiguruj funkcję Paolo w ten sposób:
function count(re, str) { if (typeof re !== "string") { return 0; } re = (re === '.') ? ('\\' + re) : re; var cre = new RegExp(re, 'g'); return ((str || '').match(cre) || []).length; }
Chciałem, aby wyrażenie regularne zostało przekazane, aby funkcja była bardziej wielokrotnego użytku, po drugie, chciałem, aby parametr był ciągiem, aby klient nie musiał tworzyć wyrażenia regularnego, ale po prostu dopasować do ciągu, na przykład standardowa metoda klasy narzędziowej typu string.
Teraz widać, że mam do czynienia z problemami z danymi wejściowymi. Z następującymi:
if (typeof re !== "string") { return 0; }
Mam zapewnienie, że wejście nie jest coś jak dosłowne
0
,false
,undefined
, lubnull
, z których żaden nie są łańcuchami. Ponieważ tych literałów nie ma w ciągu wejściowym, nie powinno być żadnych dopasowań, ale powinny one być zgodne'0'
, co jest ciągiem.Z następującymi:
re = (re === '.') ? ('\\' + re) : re;
Mam do czynienia z faktem, że konstruktor RegExp zinterpretuje (myślę, że błędnie) ciąg
'.'
jako dopasowujący wszystkie znaki\.\
Wreszcie, ponieważ używam konstruktora RegExp, muszę nadać mu
'g'
flagę globalną, aby zliczał wszystkie dopasowania, a nie tylko pierwsze, podobnie jak sugestie w innych postach.Zdaję sobie sprawę, że to bardzo późna odpowiedź, ale może być pomocna dla kogoś, kto się tu potyka. BTW, oto wersja TypeScript:
function count(re: string, str: string): number { if (typeof re !== 'string') { return 0; } re = (re === '.') ? ('\\' + re) : re; const cre = new RegExp(re, 'g'); return ((str || '').match(cre) || []).length; }
źródło
co powiesz na to
function isint(str){ if(str.match(/\d/g).length==str.length){ return true; } else { return false } }
źródło