Подсчитать количество вхождений символа в строку в JavaScript
мне нужно посчитать количество вхождений символа в строку.
например, предположим, что моя строка содержит:
var mainStr = "str1,str2,str3,str4";
Я хочу найти количество запятых , символ, который равен 3. И количество отдельных строк после разделения по запятым, которое равно 4.
мне также нужно проверить, что каждая из строк, т. е. str1 или str2 или str3 или str4, не должна превышать, скажем, 15 символов.
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используйте литерал регулярного выражения, если вы знаете, что вы ищете заранее, если нет, вы можете использовать
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 //>22.
"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:24.
поиск один характер
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 методов подсчета символов, поэтому мы можем напрямую объединять и делиться своими идеями-просто для удовольствия, и, возможно, некоторые интересные ориентиры :)
добавьте эту функцию в прототип 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; } }пожалуйста, дайте мне знать, если вы обнаружите, что эта реализация не работает или не соответствует некоторым стандартам! :)
обновление Вы можете использовать:
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
насчет строки.сплит(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