Простой способ подсчета вхождений символов в строке [дубликат]
этот вопрос уже есть ответ здесь:
есть ли простой способ (вместо обхода вручную всей строки или цикла для indexOf), чтобы найти, сколько раз символ появляется в строке?
скажем, у нас есть "abdsd3$asda$asasdd$sadas", и мы хотим, чтобы $ появился 3 раза.
15 ответов:
String s = "..."; int counter = 0; for( int i=0; i<s.length(); i++ ) { if( s.charAt(i) == '$' ) { counter++; } }
Это, безусловно, самый быстрый способ. Регулярные выражения здесь намного медленнее и, возможно, сложнее понять.
функциональный стиль (Java 8, просто для удовольствия):
str.chars().filter(num -> num == '$').count()
Не оптимальный, но простой способ подсчета вхождений:
String s = "..."; int counter = s.split("\$", -1).length - 1;
Примечание:
- знак доллара-это специальный символ регулярного выражения, поэтому он должен быть экранированы.
- обратная косая черта является специальным символом для escape-символов, таких как новые строки, поэтому он должен быть экранирован с обратной косой чертой.
- второй аргумент split предотвращает удаление пустых конечных строк.
можно использовать Apache Commons'
StringUtils.countMatches(String string, String subStringToCount)
.
Так как вы все равно сканируете всю строку, вы можете построить полное количество символов и выполнить любое количество поисков, все для той же большой стоимости (n):
public static Map<Character,Integer> getCharFreq(String s) { Map<Character,Integer> charFreq = new HashMap<Character,Integer>(); if (s != null) { for (Character c : s.toCharArray()) { Integer count = charFreq.get(c); int newCount = (count==null ? 1 : count+1); charFreq.put(c, newCount); } } return charFreq; } // ... String s = "abdsd3$asda$asasdd$sadas"; Map counts = getCharFreq(s); counts.get('$'); // => 3 counts.get('a'); // => 7 counts.get('s'); // => 6
подсчет частоты символов является общей задачей для некоторых приложений (таких как образование), но не достаточно общей, чтобы гарантировать включение в основные API Java. Таким образом, вам, вероятно, придется написать свою собственную функцию.
вы также можете использовать a для каждого цикла. Я думаю, что это проще читать.
int occurrences = 0; for(char c : yourString.toCharArray()){ if(c == '$'){ occurrences++; } }
Я считаю, что "один лайнер", что вы ожидали получить это:
"abdsd3$asda$asasdd$sadas".replaceAll( "[^$]*($)?", "" ).length();
помните, что требования:
(вместо обхода вручную всей строки или цикл для indexOf)
и позвольте мне добавить: что в основе этого вопроса звучит так, как будто "любая петля" не нужна и нет требования к скорости. Я считаю, что подтекст этого вопроса крутость фактор.
обход строки, вероятно, наиболее эффективен, хотя использование регулярного выражения для этого может привести к более чистому коду (хотя вы всегда можете скрыть свой код обхода в функции).
Ну есть куча разных утилит для этого, например, Apache Commons Lang String Utils
но в конце концов, он должен перебирать строку, чтобы подсчитать вхождения так или иначе.
обратите внимание также, что
countMatches
метод выше имеет следующую подпись, поэтому будет работать и для подстрок.
public static int countMatches(String str, String sub)
источник для этого (с здесь):
public static int countMatches(String str, String sub) { if (isEmpty(str) || isEmpty(sub)) { return 0; } int count = 0; int idx = 0; while ((idx = str.indexOf(sub, idx)) != -1) { count++; idx += sub.length(); } return count; }
мне было любопытно, если они перебирали строку или использовали регулярное выражение.
что-то более функциональное, без регулярных выражений:
public static int count(String s, char c) { return s.length()==0 ? 0 : (s.charAt(0)==c ? 1 : 0) + count(s.substring(1),c); }
это не хвост рекурсивный, для ясности.
Это простой код, но, конечно, немного медленнее.
String s = ...; int countDollar = s.length()-s.replaceAll("\$","").length(); int counta = s.length()-s.replaceAll("a","").length();
еще лучший ответ здесь в дублировать вопрос
вы можете посмотреть на сортировку строки-рассматривать ее как массив символов - а затем сделать модифицированный двоичный поиск, который подсчитывает вхождения? Но я согласен с @tofutim, что работающих в ней является наиболее эффективным -- О(N) против o(П * Фремонт, Калифорния) + о(Фремонт, Калифорния)
есть еще один способ подсчета количества символов в каждой строке. Предполагая, что у нас есть строка в виде
String str = "abfdvdvdfv"
затем мы можем подсчитать количество раз, когда каждый символ появляется, пройдя только один раз как
for (int i = 0; i < str.length(); i++) { if(null==map.get(str.charAt(i)+"")) { map.put(str.charAt(i)+"", new Integer(1)); } else { Integer count = map.get(str.charAt(i)+""); map.put(str.charAt(i)+"", count+1); } }
затем мы можем проверить вывод, пройдя по карте как
for (Map.Entry<String, Integer> entry:map.entrySet()) { System.out.println(entry.getKey()+" count is : "+entry.getValue()) }