Как посчитать вхождение строки в строку?

Как я могу посчитать, сколько раз конкретная строка встречается в другой строке. Например, это то, что я пытаюсь сделать в Javascript:

var temp = "This is a string.";
alert(temp.count("is")); //should output '2'

45 ответов

Решение

g в регулярном выражении (сокращение от global) говорит, что нужно искать всю строку, а не просто найти первое вхождение. Это соответствует is дважды:

var temp = "This is a string.";
var count = (temp.match(/is/g) || []).length;
console.log(count);

И, если нет совпадений, он возвращает 0:

var temp = "Hello World!";
var count = (temp.match(/is/g) || []).length;
console.log(count);

/** Function that count occurrences of a substring in a string;
 * @param {String} string               The string
 * @param {String} subString            The sub string to search for
 * @param {Boolean} [allowOverlapping]  Optional. (Default:false)
 *
 * @author Vitim.us https://gist.github.com/victornpb/7736865
 * @see Unit Test https://jsfiddle.net/Victornpb/5axuh96u/
 * @see http://stackru.com/questions/4009756/how-to-count-string-occurrence-in-string/7924240#7924240
 */
function occurrences(string, subString, allowOverlapping) {

    string += "";
    subString += "";
    if (subString.length <= 0) return (string.length + 1);

    var n = 0,
        pos = 0,
        step = allowOverlapping ? 1 : subString.length;

    while (true) {
        pos = string.indexOf(subString, pos);
        if (pos >= 0) {
            ++n;
            pos += step;
        } else break;
    }
    return n;
}

использование

occurrences("foofoofoo", "bar"); //0

occurrences("foofoofoo", "foo"); //3

occurrences("foofoofoo", "foofoo"); //1

allowOverlapping

occurrences("foofoofoo", "foofoo", true); //2

Матчи:

  foofoofoo
1 `----´
2    `----´

Модульный тест

эталонный тест

Я провел тестирование производительности, и моя функция более чем в 10 раз быстрее, чем функция соответствия регулярному выражению, опубликованная gumbo. В моем тесте длина строки составляет 25 символов. с 2 вхождениями персонажа "о". Я выполнил 1 000 000 раз в Safari.

Safari 5.1

Тест> Общее время выполнения: 5617 мс (регулярное выражение)

Тест> Общее время выполнения: 881 мс (моя функция в 6,4 раза быстрее)

Firefox 4

Тест> Общее время выполнения: 8547 мс (Rexexp)

Тест> Общее время выполнения: 634 мс (моя функция в 13,5 раз быстрее)


Изменить: изменения, которые я сделал

  • длина кешированной подстроки

  • добавлено приведение типов к строке.

  • добавлен необязательный параметр allowOverlapping

  • исправлен правильный вывод для "" пустого подстроки.

Суть
function countInstances(string, word) {
   return string.split(word).length - 1;
}

Вы можете попробовать это:

var theString = "This is a string.";
console.log(theString.split("is").length - 1);

Мое решение:

var temp = "This is a string.";

function countOcurrences(str, value) {
  var regExp = new RegExp(value, "gi");
  return (str.match(regExp) || []).length;
}

console.log(countOcurrences(temp, 'is'));

Ты можешь использовать match определить такую ​​функцию:

String.prototype.count = function(search) {
    var m = this.match(new RegExp(search.toString().replace(/(?=[.\\+*?[^\]$(){}\|])/g, "\\"), "g"));
    return m ? m.length:0;
}

Просто используйте код для решения Rebecca Chernoff:-)

alert(("This is a string.".match(/is/g) || []).length);

Версия без регулярных выражений:

 var string = 'This is a string',
    searchFor = 'is',
    count = 0,
    pos = string.indexOf(searchFor);

while (pos > -1) {
    ++count;
    pos = string.indexOf(searchFor, ++pos);
}

console.log(count);   // 2

String.prototype.Count = function (find) { return this.split(find).length - 1; } "This is a string.".Count("is");

Это вернет 2.

Вот самая быстрая функция!

Почему это быстрее?

  • Не проверяет char по char (за 1 исключением)
  • Использует время и увеличивает на 1 переменную (число символов переменной) по сравнению с циклом for, проверяющим длину и увеличивающим 2 переменной (обычно это переменная i и переменная с количеством символов)
  • Использует путь меньше в
  • Не использует регулярные выражения!
  • Использует (надеюсь) высоко оптимизированную функцию
  • Все операции объединены настолько, насколько это возможно, что позволяет избежать замедления из-за нескольких операций.

    String.prototype.timesCharExist=function(c){var t=0,l=0,c=(c+'')[0];while(l=this.indexOf(c,l)+1)++t;return t};
    

Вот более медленная и более читаемая версия:

    String.prototype.timesCharExist = function ( chr ) {
        var total = 0, last_location = 0, single_char = ( chr + '' )[0];
        while( last_location = this.indexOf( single_char, last_location ) + 1 )
        {
            total = total + 1;
        }
        return total;
    };

Этот медленнее из-за счетчика, длинных имен var и неправильного использования 1 var.

Чтобы использовать это, вы просто делаете это:

    'The char "a" only shows up twice'.timesCharExist('a');

Изменить: (2013/12/16)

НЕ используйте с Opera 12.16 или старше! это займет почти в 2,5 раза больше, чем решение регулярных выражений!

В Chrome это решение займет от 14 до 20 мс для 1000000 символов.

Решение регулярных выражений занимает 11-14ms для того же количества.

Используя функцию (снаружи String.prototype) займет около 10-13мс.

Вот код, используемый:

    String.prototype.timesCharExist=function(c){var t=0,l=0,c=(c+'')[0];while(l=this.indexOf(c,l)+1)++t;return t};

    var x=Array(100001).join('1234567890');

    console.time('proto');x.timesCharExist('1');console.timeEnd('proto');

    console.time('regex');x.match(/1/g).length;console.timeEnd('regex');

    var timesCharExist=function(x,c){var t=0,l=0,c=(c+'')[0];while(l=x.indexOf(c,l)+1)++t;return t;};

    console.time('func');timesCharExist(x,'1');console.timeEnd('func');

Результат всех решений должен быть 100 000!

Примечание: если вы хотите, чтобы эта функция считала более 1 символа, измените где c=(c+'')[0] в c=c+''

var temp = "This is a string.";
console.log((temp.match(new RegExp("is", "g")) || []).length);

Простым способом было бы разделить строку на требуемое слово, слово, для которого мы хотим вычислить количество вхождений, и вычесть 1 из количества частей:

      function checkOccurences(string, word) {
      return string.split(word).length - 1;
}
const text="Let us see. see above, see below, see forward, see backward, see left, see right until we will be right"; 
const count=countOccurences(text,"see "); // 2

Я думаю, что цель регулярных выражений сильно отличается от indexOf, indexOf просто найдите вхождение определенной строки, в то время как в регулярных выражениях вы можете использовать такие символы, как [A-Z] это означает, что он найдет любой заглавный символ в слове без указания фактического символа.

Пример:

 var index = "This is a string".indexOf("is");
 console.log(index);
 var length = "This is a string".match(/[a-z]/g).length;
 // where [a-z] is a regex wildcard expression thats why its slower
 console.log(length);

       var myString = "This is a string.";
        var foundAtPosition = 0;
        var Count = 0;
        while (foundAtPosition != -1)
        {
            foundAtPosition = myString.indexOf("is",foundAtPosition);
            if (foundAtPosition != -1)
            {
                Count++;
                foundAtPosition++;
            }
        }
        document.write("There are " + Count + " occurrences of the word IS");

См.:- подсчитать подстроку в строке для пошагового объяснения.

Опираясь на @Vittim.us ответ выше. Мне нравится контроль, который дает мне его метод, что облегчает его расширение, но мне нужно было добавить регистронезависимость и ограничить совпадения целыми словами с поддержкой пунктуации. (например, "ванна" означает "принять ванну", но не "купание")

Регулярное выражение для пунктуации получено по адресу: /questions/42899019/kak-ya-mogu-udalit-vse-znaki-prepinaniya-iz-stroki-v-javascript-s-pomoschyu-regulyarnyih-vyirazhenij/42899036#42899036 ( Как я могу удалить все знаки препинания из строки в JavaScript с помощью регулярного выражения?)

function keywordOccurrences(string, subString, allowOverlapping, caseInsensitive, wholeWord)
{

    string += "";
    subString += "";
    if (subString.length <= 0) return (string.length + 1); //deal with empty strings

    if(caseInsensitive)
    {            
        string = string.toLowerCase();
        subString = subString.toLowerCase();
    }

    var n = 0,
        pos = 0,
        step = allowOverlapping ? 1 : subString.length,
        stringLength = string.length,
        subStringLength = subString.length;

    while (true)
    {
        pos = string.indexOf(subString, pos);
        if (pos >= 0)
        {
            var matchPos = pos;
            pos += step; //slide forward the position pointer no matter what

            if(wholeWord) //only whole word matches are desired
            {
                if(matchPos > 0) //if the string is not at the very beginning we need to check if the previous character is whitespace
                {                        
                    if(!/[\s\u2000-\u206F\u2E00-\u2E7F\\'!"#$%&\(\)*+,\-.\/:;<=>?@\[\]^_`{|}~]/.test(string[matchPos - 1])) //ignore punctuation
                    {
                        continue; //then this is not a match
                    }
                }

                var matchEnd = matchPos + subStringLength;
                if(matchEnd < stringLength - 1)
                {                        
                    if (!/[\s\u2000-\u206F\u2E00-\u2E7F\\'!"#$%&\(\)*+,\-.\/:;<=>?@\[\]^_`{|}~]/.test(string[matchEnd])) //ignore punctuation
                    {
                        continue; //then this is not a match
                    }
                }
            }

            ++n;                
        } else break;
    }
    return n;
}

Пожалуйста, не стесняйтесь изменять и реорганизовывать этот ответ, если вы обнаружите ошибки или улучшения.

Мы можем использовать js splitфункция, и ее длина минус 1 будет количеством вхождений.

      var temp = "This is a string.";
alert(temp.split('is').length-1);

Для любого, кто найдет этот поток в будущем, обратите внимание, что принятый ответ не всегда вернет правильное значение, если вы его обобщите, так как он захлебнется операторами регулярного выражения, такими как $ а также ., Вот лучшая версия, которая может справиться с любой иглой:

function occurrences (haystack, needle) {
  var _needle = needle
    .replace(/\[/g, '\\[')
    .replace(/\]/g, '\\]')
  return (
    haystack.match(new RegExp('[' + _needle + ']', 'g')) || []
  ).length
}

Супер пупер старый, но мне нужно было сделать что-то подобное сегодня и только подумал, чтобы проверить это потом. Работает довольно быстро для меня.

String.prototype.count = function(substr,start,overlap) {
    overlap = overlap || false;
    start = start || 0;

    var count = 0, 
        offset = overlap ? 1 : substr.length;

    while((start = this.indexOf(substr, start) + offset) !== (offset - 1))
        ++count;
    return count;
};
 function substrCount( str, x ) {
   let count = -1, pos = 0;
   do {
     pos = str.indexOf( x, pos ) + 1;
     count++;
   } while( pos > 0 );
   return count;
 }

function get_occurrence(varS,string){//Find All Occurrences
        c=(string.split(varS).length - 1);
        return c;
    }
    temp="This is a string.";
    console.log("Total Occurrence is "+get_occurrence("is",temp));

Используйте get_occurrence(varS,string), чтобы найти вхождение как символов, так и строки в строку.

Попытайся

<?php 
$str = "33,33,56,89,56,56";
echo substr_count($str, '56');
?>

<script type="text/javascript">
var temp = "33,33,56,89,56,56";
var count = temp.match(/56/g);  
alert(count.length);
</script>

Простая версия без регулярных выражений:

var temp = "This is a string.";

var count = (temp.split('is').length - 1);

alert(count);

добавил эту оптимизацию:

Как посчитать вхождение строки в строку?

Это, вероятно, самая быстрая реализация здесь, но она была бы еще быстрее, если бы вы заменили «++pos» на «pos+=searchFor.length» — hanshenrik

      function occurrences(str_, subStr) {
  let occurence_count = 0
  let pos = -subStr.length
  while ((pos = str_.indexOf(subStr, pos + subStr.length)) > -1) {
    occurence_count++
  }
  return occurence_count
}

Никто никогда не увидит этого, но хорошо бы время от времени возвращать функции рекурсии и стрелок (каламбур славно предназначен)

String.prototype.occurrencesOf = function(s, i) {
 return (n => (n === -1) ? 0 : 1 + this.occurrencesOf(s, n + 1))(this.indexOf(s, (i || 0)));
};

ES2020 предлагает новый MatchAll, который может быть полезен в этом конкретном контексте.

Здесь мы создаем новое регулярное выражение, убедитесь, что вы передали в функцию букву g.

Преобразуйте результат с помощью Array.from и посчитайте длину, которая вернет 2 в соответствии с желаемым выходом исходного запрашивающего.

Вот мое решение. Я надеюсь, что это поможет кому-то

      const countOccurence = (string, char) => {
const chars = string.match(new RegExp(char, 'g')).length
return chars;
}

Вот мое решение в 2022 году с использованием map() и filter() :

      string = "Xanthous: A person with yellow hair. Her hair was very xanthous in colour."       
count = string.split('').map((e,i) => { if(e === 'e') return i;}).filter(Boolean).length

Просто для удовольствия от использования этих функций. В примере подсчитывается количество букв «е» в моей строке.

Это то же самое, что и использование функции match():

      (string.match(/e/g)||[]).length

или просто функция split():

      string.split('e').length - 1

Я думаю, что лучше всего использовать match(), потому что он потребляет меньше ресурсов! Мой ответ просто для удовольствия и чтобы показать, что есть много возможностей решить эту проблему.

Это очень старая тема, с которой мне приходилось сталкиваться, но, поскольку многие отдали свои ответы, я хочу помочь кому-нибудь с этим простым кодом.

var search_value = "This is a dummy sentence!";
var letter = 'a'; /*Can take any letter, have put in a var if anyone wants to use this variable dynamically*/
letter = letter[letter.length - 1];
var count;
for (var i = count = 0; i < search_value.length; count += (search_value[i++] == letter));
console.log(count);

Я не уверен, что это самое быстрое решение, но я предпочел его для простоты и не использовать регулярные выражения (я просто не люблю их использовать!)

Вы можете попробовать это

let count = s.length - s.replace(/is/g, "").length;
      const getLetterMatchCount = (guessedWord, secretWord) => {
  const secretLetters = secretWord.split('');
  const guessedLetterSet = new Set(guessedWord);
  return secretLetters.filter(letter => guessedLetterSet.has(letter)).length;
};
const str = "rahul";
const str1 = "rajendra";

getLetterMatchCount(str, str1)
Другие вопросы по тегам