Подсчитайте количество вхождений символа в строку в Javascript - PullRequest
435 голосов
/ 19 мая 2009

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

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

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

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

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

Ответы [ 30 ]

632 голосов
/ 19 мая 2009

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

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

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

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

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

186 голосов
/ 20 мая 2012

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

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

1

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

2

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

разделять не рекомендуется. Ресурс голоден. Выделяет новые экземпляры Array для каждого совпадения. Не пытайтесь сделать это для> 100 МБ файла через FileReader. На самом деле вы можете легко наблюдать за использованием ресурса EXACT, используя Chrome profiler option.

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

Обновление:

5

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

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

18 голосов
/ 08 января 2015

Добавьте эту функцию в прототип 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
9 голосов
/ 19 мая 2009

Быстрый Google поиск получил это (от http://www.codecodex.com/wiki/index.php?title=Count_the_number_of_occurrences_of_a_specific_character_in_a_string#JavaScript)

String.prototype.count=function(s1) { 
    return (this.length - this.replace(new RegExp(s1,"g"), '').length) / s1.length;
}

Используйте это так:

test = 'one,two,three,four'
commas = test.count(',') // returns 3
5 голосов
/ 07 мая 2014

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

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

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

5 голосов
/ 29 мая 2018

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

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

4 голосов
/ 15 июля 2015

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

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

просто удали все, что не похоже на твой символ но это не выглядит хорошо со строкой в ​​качестве ввода

4 голосов
/ 16 октября 2016

Вот аналогичное решение, но оно использует 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.

4 голосов
/ 30 июня 2016

Производительность Split против 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");
3 голосов
/ 06 мая 2015

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

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 из строки включается в поиск.

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