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



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



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



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


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



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

1654   28  

28 ответов:

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

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 сплит идет вперед в скорости, по крайней мере, в Chrome, но снова создание дополнительного массива просто не кажется разумным.

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

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

1.

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

2.

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

сплит не рекомендуется. Ресурс голоден. Выделяет новые экземпляры "массива" для каждого соответствия. Не пытайтесь сделать это для файла >100 МБ через FileReader. Вы можете на самом деле легко наблюдать точное использование ресурсов с помощью профилировщик 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

обновление:

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

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

https://gist.github.com/2757250

добавьте эту функцию в прототип 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

быстрый 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

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

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

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

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

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

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

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

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/

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

обновление Вы можете использовать:

    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

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

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

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

самый простой способ я узнал...

пример

str = 'mississippi';

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

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

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

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

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

вот аналогичное решение, но оно использует reduce

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

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

Если вы используете лодашь, то _.графби метод сделать это:

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

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

_.countBy(['ab', 'cd', 'ab'])['ab'] //2
s = 'dir/dir/dir/dir/'
for(i=l=0;i<s.length;i++)
if(s[i] == '/')
l++

насчет строки.сплит(desiredCharecter).длина-1

пример:

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

Я использую узел.js V. 6. 0. 0 и самый быстрый-с индексом (3-й метод в ответе Ло Зауэра).

второй:

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

вот один почти так же быстро, как split и replace методы, которые немного быстрее, чем метод regex (в chrome).

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

и здесь:

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

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

ниже используется регулярное выражение для проверки длины. 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.");
}

мое решение:

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

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

код:

// 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

пятый способ в Лев 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;

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

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

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

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

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

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

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

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

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

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
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 вы можете использовать приведенный выше код, чтобы получить вхождение символа в строку.

Вы можете остальное строку и работать с ней как массив элементов с помощью

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

console.log(commas);

или

const mainStr = 'str1,str2,str3,str4';
const commas = [...mainStr].reduce((a, c) => c === ',' ? ++a : a, 0);

console.log(commas);

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

Comments

    Ничего не найдено.