Javascript'te bir normal ifadenin eşleşme sayısını sayın


100

Bir metin yığınındaki boşluk / sekme / satırsonu sayısını saymak için bir normal ifade yazmak istedim. Bu yüzden safça şunları yazdım: -

numSpaces : function(text) { 
    return text.match(/\s/).length; 
}

Bilinmeyen bazı nedenlerden dolayı her zaman geri döner 1. Yukarıdaki ifadedeki sorun nedir? O zamandan beri sorunu aşağıdakilerle çözdüm: -

numSpaces : function(text) { 
    return (text.split(/\s/).length -1); 
}

Yanıtlar:


196

tl; dr: Genel Desen Sayacı

// THIS IS WHAT YOU NEED
const count = (str) => {
  const re = /YOUR_PATTERN_HERE/g
  return ((str || '').match(re) || []).length
}

Bir dizedeki bir normal ifade deseninin oluşum sayısını saymanın genel bir yolunu arayanlar ve sıfır oluşum varsa başarısız olmasını istemeyenler için bu kod ihtiyacınız olan şeydir. İşte bir gösteri:

/*
 *  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'`)

Orijinal Cevap

İlk kodunuzla ilgili sorun, genel tanımlayıcının eksik olmasıdır :

>>> 'hi there how are you'.match(/\s/g).length;
4

Normal gifadenin parçası olmadan, yalnızca ilk geçtiği yerle eşleşecek ve orada duracaktır.

Ayrıca normal ifadenizin art arda boşlukları iki kez sayacağını unutmayın:

>>> 'hi  there'.match(/\s/g).length;
2

Bu istenmiyorsa, bunu yapabilirsiniz:

>>> 'hi  there'.match(/\s+/g).length;
1

5
Bu, girişinizde en az bir boşluk olduğu sürece çalışır. Aksi takdirde match () can sıkıcı bir şekilde null döndürür.
sfink

3
sfink haklı, maçın () null döndürülüp döndürülmediğini kesinlikle kontrol etmek istiyorsunuz:var result = text.match(/\s/g); return result ? result.length : 0;
Gras Double

37
Bu yapıyı kullanarak da boşa karşı koruma sağlayabilirsiniz:( str.match(...) || [] ).length
a'r

11

Daha önceki cevabımda belirtildiği gibi , RegExp.exec()tüm eşleşmeleri yinelemek ve her örneği saymak için kullanabilirsiniz ; Avantaj yalnızca bellekle sınırlıdır, çünkü genel olarak kullanmaktan yaklaşık% 20 daha yavaştır String.match().

var re = /\s/g,
count = 0;

while (re.exec(text) !== null) {
    ++count;
}

return count;


2

('my string'.match(/\s/g) || []).length;


1
Bence || []yanlış yere koydunuz, olmalı('my string'.match(/\s/g) || []).length
woojoo666

0

Bu kesinlikle çok fazla tuzağı olan bir şey. Paolo Bergantino'nun cevabıyla çalışıyordum ve bunun bile bazı sınırlamaları olduğunu fark ettim. Tarihlerin dizgi temsilleriyle çalışmayı ana problemlerin bazılarını hızlıca bulmak için iyi bir yer buldum. Bunun gibi bir giriş dizesiyle başlayın: '12-2-2019 5:1:48.670'

ve Paolo'nun işlevini şu şekilde ayarlayın:

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

Normal ifadenin iletilmesini istedim, böylece işlev daha yeniden kullanılabilir olsun, ikincisi, parametrenin bir dize olmasını istedim, böylece istemcinin normal ifadeyi yapması gerekmez, sadece dizeyle eşleşir, örneğin standart bir dize yardımcı programı sınıfı yöntemi.

Şimdi, burada girdiyle ilgili sorunlarla uğraştığımı görebilirsiniz. Takip ederek:

if (typeof re !== "string") {
    return 0;
}

Ben girdi değişmezi gibi bir şey değil sağlanması ediyorum 0, false, undefined, veya null, hiçbiri dizeleri olmak üzere. Bu değişmez değerler girdi dizesinde olmadığından, eşleşme olmamalıdır, ancak eşleşmelidir '0', bu bir dizedir.

Takip ederek:

re = (re === '.') ? ('\\' + re) : re;

RegExp yapıcısının dizeyi '.'tüm karakter eşleştirici olarak yorumlayacağı gerçeğiyle uğraşıyorum (sanırım yanlış bir şekilde)\.\

Son olarak, RegExp yapıcısını kullandığım için 'g', diğer gönderilerdeki önerilere benzer şekilde yalnızca ilkini değil, tüm eşleşmeleri sayması için ona genel bayrağı vermem gerekiyor .

Bunun son derece geç bir cevap olduğunun farkındayım, ama burada tökezleyen birine yardımcı olabilir. BTW işte TypeScript sürümü:

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

-2

buna ne dersin

function isint(str){
    if(str.match(/\d/g).length==str.length){
        return true;
    }
    else {
         return false
    }
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.