Простой способ подсчета вхождений символов в строке [дубликат]


этот вопрос уже есть ответ здесь:

есть ли простой способ (вместо обхода вручную всей строки или цикла для indexOf), чтобы найти, сколько раз символ появляется в строке?

скажем, у нас есть "abdsd3$asda$asasdd$sadas", и мы хотим, чтобы $ появился 3 раза.

15 52

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

}
 public static int countChars(String input,char find){      
            if(input.indexOf(find) != -1){          
            return  countChars(input.substring(0, input.indexOf(find)), find)+ 
                countChars(input.substring(input.indexOf(find)+1),find) + 1;
            }
            else {
                return 0;
            }

        }