Подтвердить что ты не робот

Подсчитайте количество вхождений символа в строке в Javascript

Мне нужно подсчитать количество вхождений символа в строку.

Например, предположим, что моя строка содержит:

var mainStr = "str1,str2,str3,str4";

Я хочу найти символ запятой ,, который равен 3. И количество отдельных строк после разделения по запятой, которое равно 4.

Мне также нужно проверить, что каждая из строк i.e str1 или str2 или str3 или str4 не должна превышать, например, 15 символов.

4b9b3361

Ответ 1

Я обновил этот ответ. Мне нравится лучше использовать матч, но он медленнее:

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

jsfiddle

Используйте литерал регулярных выражений, если вы знаете, что вы ищете заранее, если не можете использовать конструктор RegExp и передать в качестве аргумента флаг g.

match возвращает null без результатов, поэтому || []

Оригинальный ответ, который я сделал в 2009 году, приведен ниже. Он создает массив без необходимости, но с использованием разделения быстрее (по состоянию на сентябрь 2014 года). Я амбивалентен, если мне действительно нужна скорость, не было бы вопроса, что я бы использовал раскол, но я бы предпочел использовать совпадение.

Старый ответ (с 2009 года):

Если вы ищете запятую:

(mainStr.split(",").length - 1) //3

Если вы ищете str

(mainStr.split("str").length - 1) //4

Как в ответе @Lo, так и в моем собственном глупое jsperf test раскол идет вперед по скорости, по крайней мере в Chrome, но снова создает дополнительные массив просто не кажется нормальным.

Ответ 2

Существует не менее четырех способов. Наилучший вариант, который также должен быть самым быстрым в отношении к исходному движку RegEx, находится наверху. jsperf.com в настоящее время недоступен, в противном случае я бы предоставил вам статистику производительности.

Обновить. Пожалуйста, найдите тесты производительности здесь и запустите их, чтобы внести свой вклад в результаты вашей работы. Специфика результатов будет дана позже.

1.

 ("this is foo bar".match(/o/g)||[]).length
 //>2

2.

"this is foo bar".split("o").length-1
 //>2

не рекомендуется. Ресурс голоден. Выделяет новые экземпляры "Массив" для каждого совпадения. Не пытайтесь использовать файл > 100MB через FileReader. Фактически вы можете легко наблюдать за использованием EXACT-ресурсов с помощью опции профайлера Chrome.

3.

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

4.

поиск одного символа

var stringsearch = "o"
   ,str = "this is foo bar";
for(var i=count=0; i<str.length; count+=+(stringsearch===str[i++]));
 //>count:2

Update:

5.

отображение и фильтрация элементов, не рекомендуется из-за его общего назначения ресурсов, а не с использованием генераторов Питона

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

Доля: Я сделал это gist, в настоящее время 8 методов подсчета символов, поэтому мы можем напрямую объединять и делиться нашими идеями - просто для удовольствия и, возможно, для некоторых интересных эталонных тестов: )

https://gist.github.com/2757250

Ответ 3

Добавьте эту функцию в прототип sting:

String.prototype.count=function(c) { 
  var result = 0, i = 0;
  for(i;i<this.length;i++)if(this[i]==c)result++;
  return result;
};

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

console.log("strings".count("s")); //2

Ответ 5

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

mainStr.split(',').length //дает 4, которое является числом строк после разделения, используя запятую разделителя

mainStr.split(',').length - 1 //дает 3, которое является числом запятой

Ответ 6

Я обнаружил, что лучший подход для поиска символа в очень большой строке (например, длиной 1 000 000 символов) - это использовать метод replace().

window.count_replace = function (str, schar) {
    return str.length - str.replace(RegExp(schar), '').length;
};

Вы можете увидеть еще один набор JSPerf для тестирования этого метода наряду с другими методами поиска символа в строке.

Ответ 7

ok, другой с регулярным выражением - вероятно, не быстрый, но короткий и лучше читаемый, а другие, в моем случае просто '_' для подсчета

key.replace(/[^_]/g,'').length

просто удалите все, что не похоже на ваш char но он не выглядит красивым с помощью строки в качестве входного

Ответ 8

Производительность 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");

Ответ 9

Вот аналогичное решение, но оно использует Array.ptototype.reduce

function countCharacters(char, string) {
  return string.split('').reduce((acc, ch) => ch === char ? acc + 1: acc, 0)
}

Как уже упоминалось, String.prototype.split работает намного быстрее, чем String.prototype.replace.

Ответ 10

Самый простой способ узнать...

Пример -

str = 'mississippi';

function find_occurences(str, char_to_count){
    return str.split(char_to_count).length - 1;
}

find_occurences(str, 'i') //outputs 4

Ответ 11

Я работал над небольшим проектом, для которого требовался счетчик подстроки. Поиск неправильных фраз давал мне никаких результатов, однако после написания моей собственной реализации я наткнулся на этот вопрос. Во всяком случае, вот мой путь, он, вероятно, медленнее, чем большинство здесь, но может быть полезным для кого-то:

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

http://jsfiddle.net/5ZzHt/1/

Пожалуйста, дайте мне знать, если вы обнаружите, что эта реализация терпит неудачу или не соответствует некоторым стандартам!:)

UPDATE Вы можете заменить:

    for (var i = 0; i < input.length; i++) {

С

for (var i = 0, input_length = input.length; i < input_length; i++) {

Интересное чтение, обсуждавшее выше: http://www.erichynds.com/blog/javascript-length-property-is-a-stored-value

Ответ 12

Я немного улучшил принятый ответ, он позволяет проверять с учетом регистра/нечувствительности к регистру, а также метод, привязанный к строковому объекту:

String.prototype.count = function(lit, cis) {
    var m = this.toString().match(new RegExp(lit, ((cis) ? "gi" : "g")));
    return (m != null) ? m.length : 0;
}

lit - это строка для поиска (например, "ex" ), а cis - нечувствительность к регистру, значение по умолчанию - false, это позволит выбирать нечувствительные к регистру совпадения.


Чтобы найти строку 'I love StackOverflow.com' для строчной буквы 'o', вы должны использовать:
var amount_of_os = 'I love StackOverflow.com'.count('o');

amount_of_os будет равно 2.


Если бы мы снова искали одну и ту же строку, используя нечувствительность к регистру, вы использовали бы:
var amount_of_os = 'I love StackOverflow.com'.count('o', true);

На этот раз amount_of_os будет равно 3, так как капитал O из строки будет включен в поиск.

Ответ 13

Если вы используете lodash, метод _. countBy сделает это:

_.countBy("abcda")['a'] //2

Этот метод также работает с массивом:

_.countBy(['ab', 'cd', 'ab'])['ab'] //2

Ответ 14

Вы также можете отдохнуть свою строку и работать с ней как массив элементов, используя

const mainStr = 'str1,str2,str3,str4';
const commas = [...mainStr].filter(l => l === ',').length;

console.log(commas);

Ответ 15

Следующее использует регулярное выражение для проверки длины. testex гарантирует, что у вас нет 16 или более последовательных символов без запятой. Если он проходит тест, он переходит к разделению строки. подсчет запятых так же просто, как подсчет токенов минус один.

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.");
}

Ответ 16

s = 'dir/dir/dir/dir/'
for(i=l=0;i<s.length;i++)
if(s[i] == '/')
l++

Ответ 17

Как насчет string.split(wishCharecter).length-1

Пример:

var str = "hellow how is life"; var len = str.split( "h" ). length-1; будет давать счет 2 для символа "h" в приведенной выше строке;

Ответ 18

Я использую Node.js v.6.0.0, а самый быстрый - с индексом (третий метод в ответе Lo Sauer).

Вторая:

function count(s, c) {
  var n = 0;
  for (let x of s) {
    if (x == c)
      n++;
  }
  return n;
}

Ответ 19

Здесь он почти такой же быстрый, как метод split и replace, который на крошечном бите быстрее, чем метод regex (в хром).

var num = 0;
for (ch of "str1,str2,str3,str4")
{
    if (ch === ',') num++;
}

Ответ 20

Я только что сделал очень быстрый и грязный тест на repl.it с помощью Node v7.4. Для одного символа стандарт для цикла является самым быстрым:

Некоторый код:

// 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');
}

Результаты нескольких прогонов:

 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

Ответ 21

И есть:

function character_count(string, char, ptr = 0, count = 0) {
    while (ptr = string.indexOf(char, ptr) + 1) {count ++}
    return count
}

Работает с целыми числами тоже!

Ответ 22

Мое решение:

function countOcurrences(str, value){
   var regExp = new RegExp(value, "gi");
   return str.match(regExp) ? str.match(regExp).length : 0;  
}

Ответ 23

Пятый метод в Leo Sauers отвечает неудачно, если символ находится в начале строки. например

var needle ='A',
  haystack = 'AbcAbcAbc';

haystack.split('').map( function(e,i){ if(e === needle) return i;} )
  .filter(Boolean).length;

даст 2 вместо 3, потому что фильтр funtion Boolean дает false для 0.

Другая возможная функция фильтра:

haystack.split('').map(function (e, i) {
  if (e === needle) return i;
}).filter(function (item) {
  return !isNaN(item);
}).length;

Ответ 24

Я знаю, что это может быть старый вопрос, но у меня есть простое решение для низкоуровневых новичков в JavaScript.

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

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

Пример функции: -

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

Ответ 25

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

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

Пример использования:

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

Ответ 26

Самый быстрый способ, кажется, через оператор индекса:

function charOccurances (str, char)
{
    for (var c = 0, i = 0, len = str.length; i < len; ++i)
    {
        if (str[i] == char)
        {
            ++c;
        }
    }
    return c;
}

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

charOccurances('example/path/script.js', '/') == 2

Или как функция-прототип:

String.prototype.charOccurances = function (char)
{
    for (var c = 0, i = 0, len = this.length; i < len; ++i)
    {
        if (this[i] == char)
        {
            ++c;
        }
    }
    return c;
}

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

charOccurances('example/path/script.js', '/') == 2

Ответ 27

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

В JavaScript вы можете использовать приведенный выше код, чтобы получить вхождение символа в строку.

Ответ 28

Мое решение с помощью ramda js:

const testString = 'somestringtotest'

const countLetters = R.compose(
  R.map(R.length),
  R.groupBy(R.identity),
  R.split('')
)

countLetters(testString)

Ссылка на REPL.

Ответ 29

Функция принимает строку str в качестве параметра и подсчитывает вхождение каждого уникального символа в строку. Результат приходит в паре ключ-значение для каждого символа.

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;

} 

Ответ 30

Вот мое решение. Много решений уже выложено до меня. Но я люблю делиться своим мнением здесь.

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

Здесь вы найдете мой REPL