ocorrências - count letter string java



Como faço para contar o número de ocorrências de um char em uma String? (20)

Eu tenho a string

a.b.c.d

Eu quero contar as ocorrências de '.' de uma forma idiomática, de preferência um one-liner.

(Anteriormente, eu havia expressado essa restrição como "sem loop", caso você esteja se perguntando por que todos estão tentando responder sem usar um loop).


Answer #1

A maneira mais simples de obter a resposta é a seguinte:

public static void main(String[] args) {
    String string = "a.b.c.d";
    String []splitArray = string.split("\\.");
    System.out.println("No of . chars is : " + splitArray.length-1);
}

Answer #2

Aqui está uma solução de recursão de estilo ligeiramente diferente:

public static int countOccurrences(String haystack, char needle)
{
    return countOccurrences(haystack, needle, 0);
}

private static int countOccurrences(String haystack, char needle, int accumulator)
{
    if (haystack.length() == 0) return accumulator;
    return countOccurrences(haystack.substring(1), needle, haystack.charAt(0) == needle ? accumulator + 1 : accumulator);
}

Answer #3

Bem, com uma tarefa bastante semelhante, deparei com este Thread. Eu não vi nenhuma restrição de linguagem de programação e desde groovy é executado em um java vm: Aqui está como eu fui capaz de resolver meu problema usando o Groovy.

"a.b.c.".count(".")

feito.


Answer #4

Caso você esteja usando o Spring framework, você também pode usar a classe "StringUtils". O método seria "countOccurrencesOf".


Answer #5

Em algum lugar no código, algo tem que fazer um loop. A única maneira de contornar isso é um desenrolar completo do loop:

int numDots = 0;
if (s.charAt(0) == '.') {
    numDots++;
}

if (s.charAt(1) == '.') {
    numDots++;
}


if (s.charAt(2) == '.') {
    numDots++;
}

... etc, mas então você é o único a fazer o loop, manualmente, no editor de código - em vez do computador que irá executá-lo. Veja o pseudocódigo:

create a project
position = 0
while (not end of string) {
    write check for character at position "position" (see above)
}
write code to output variable "numDots"
compile program
hand in homework
do not think of the loop that your "if"s may have been optimized and compiled to

Answer #6

Embora os métodos possam ocultá-lo, não há como contar sem um loop (ou recursão). Você quer usar um char [] por motivos de desempenho.

public static int count( final String s, final char c ) {
  final char[] chars = s.toCharArray();
  int count = 0;
  for(int i=0; i<chars.length; i++) {
    if (chars[i] == c) {
      count++;
    }
  }
  return count;
}

Usando replaceAll (que é RE) não parece ser o melhor caminho a percorrer.


Answer #7

Eu tive uma ideia semelhante a Mladen, mas o oposto ...

String s = "a.b.c.d";
int charCount = s.replaceAll("[^.]", "").length();
println(charCount);

Answer #8

Inspirado por Jon Skeet, uma versão sem loop que não vai explodir sua pilha. Também é útil como ponto de partida se você quiser usar a estrutura fork-join.

public static int countOccurrences(CharSequeunce haystack, char needle) {
    return countOccurrences(haystack, needle, 0, haystack.length);
}

// Alternatively String.substring/subsequence use to be relatively efficient
//   on most Java library implementations, but isn't any more [2013].
private static int countOccurrences(
    CharSequence haystack, char needle, int start, int end
) {
    if (start == end) {
        return 0;
    } else if (start+1 == end) {
        return haystack.charAt(start) == needle ? 1 : 0;
    } else {
        int mid = (end+start)>>>1; // Watch for integer overflow...
        return
            countOccurrences(haystack, needle, start, mid) +
            countOccurrences(haystack, needle, mid, end);
    }
}

(Aviso: Não testado, não compilado, não sensato.)

Talvez a melhor maneira (de um único encadeamento, sem suporte de par substituto) para escrevê-lo:

public static int countOccurrences(String haystack, char needle) {
    int count = 0;
    for (char c : haystack.toCharArray()) {
        if (c == needle) {
           ++count;
        }
    }
    return count;
}

Answer #9

Meu 'idiota one-liner' para isso é:

int count = StringUtils.countMatches("a.b.c.d", ".");

Por que escrever você mesmo quando já está em commons lang ?

O oneliner do Spring Framework para isso é:

int occurance = StringUtils.countOccurrencesOf("a.b.c.d", ".");

Answer #10

Minha solução "idiomática de uma linha":

int count = "a.b.c.d".length() - "a.b.c.d".replace(".", "").length();

Não tenho idéia porque uma solução que usa StringUtils é aceita.


Answer #11

O código-fonte a seguir lhe dará no.of ocorrências de uma determinada string em uma palavra digitada pelo usuário: -

import java.util.Scanner;

public class CountingOccurences {

    public static void main(String[] args) {

        Scanner inp= new Scanner(System.in);
        String str;
        char ch;
        int count=0;

        System.out.println("Enter the string:");
        str=inp.nextLine();

        while(str.length()>0)
        {
            ch=str.charAt(0);
            int i=0;

            while(str.charAt(i)==ch)
            {
                count =count+i;
                i++;
            }

            str.substring(count);
            System.out.println(ch);
            System.out.println(count);
        }

    }
}

Answer #12

Ok, inspirado pela solução de Yonatan, aqui está uma que é puramente recursiva - os únicos métodos de biblioteca usados ​​são length() e charAt() , nenhum dos quais faz nenhum loop:

public static int countOccurrences(String haystack, char needle)
{
    return countOccurrences(haystack, needle, 0);
}

private static int countOccurrences(String haystack, char needle, int index)
{
    if (index >= haystack.length())
    {
        return 0;
    }

    int contribution = haystack.charAt(index) == needle ? 1 : 0;
    return contribution + countOccurrences(haystack, needle, index+1);
}

Se a recursão conta como loop depende de qual definição exata você usa, mas é provavelmente o mais próximo que você conseguirá.

Eu não sei se a maioria das JVMs faz uma recursão final hoje em dia ... se não, você obterá o estouro de pilha de mesmo nome para seqüências de caracteres adequadamente longas, é claro.


Answer #13

Que tal agora. Ele não usa o regexp por baixo, portanto, deve ser mais rápido do que algumas das outras soluções e não usará um loop.

int count = line.length() - line.replace(".", "").length();

Answer #14

Resumir outra resposta e o que eu sei de todas as maneiras de fazer isso usando um one-liner:

   String testString = "a.b.c.d";

1) Usando o Apache Commons

int apache = StringUtils.countMatches(testString, ".");
System.out.println("apache = " + apache);

2) Usando o Spring Framework

int spring = org.springframework.util.StringUtils.countOccurrencesOf(testString, ".");
System.out.println("spring = " + spring);

3) usando substituir

int replace = testString.length() - testString.replace(".", "").length();
System.out.println("replace = " + replace);

4) Usando replaceAll (caso 1)

int replaceAll = testString.replaceAll("[^.]", "").length();
System.out.println("replaceAll = " + replaceAll);

5) Usando replaceAll (caso 2)

int replaceAllCase2 = testString.length() - testString.replaceAll("\\.", "").length();
System.out.println("replaceAll (second case) = " + replaceAllCase2);

6) Usando split

int split = testString.split("\\.",-1).length-1;
System.out.println("split = " + split);

7) Usando o Java 8 (caso 1)

long java8 = testString.chars().filter(ch -> ch =='.').count();
System.out.println("java8 = " + java8);

8) Usando o Java 8 (caso 2), pode ser melhor para o unicode do que o caso 1

long java8Case2 = testString.codePoints().filter(ch -> ch =='.').count();
System.out.println("java8 (second case) = " + java8Case2);

9) Usando o StringTokenizer

int stringTokenizer = new StringTokenizer(" " +testString + " ", ".").countTokens()-1;
System.out.println("stringTokenizer = " + stringTokenizer);

Do comentário : Tenha cuidado com o StringTokenizer, pois abcd funcionará, mas para um ... bc ... d ou ... abcd ou a .... b ...... c ..... d ... ou etc. não funcionará. Apenas contará para. entre os personagens apenas uma vez

Mais informações no github

github (usando JMH , mode = AverageTime, score 0.010 better then 0.351 ):

Benchmark              Mode  Cnt  Score    Error  Units
1. countMatches        avgt    5  0.010 ±  0.001  us/op
2. countOccurrencesOf  avgt    5  0.010 ±  0.001  us/op
3. stringTokenizer     avgt    5  0.028 ±  0.002  us/op
4. java8_1             avgt    5  0.077 ±  0.005  us/op
5. java8_2             avgt    5  0.078 ±  0.003  us/op
6. split               avgt    5  0.137 ±  0.009  us/op
7. replaceAll_2        avgt    5  0.302 ±  0.047  us/op
8. replace             avgt    5  0.303 ±  0.034  us/op
9. replaceAll_1        avgt    5  0.351 ±  0.045  us/op

Answer #15

Um exemplo mais curto é

String text = "a.b.c.d";
int count = text.split("\\.",-1).length-1;

Answer #16

Usando Coleções do Eclipse

int count = CharAdapter.adapt("a.b.c.d").count(c -> c == '.');

Se você tiver mais de um caractere para contar, você pode usar um CharBag seguinte maneira:

CharBag bag = CharAdapter.adapt("a.b.c.d").toBag();
int count = bag.occurrencesOf('.');

Nota: Eu sou um committer para coleções do Eclipse.


Answer #17

Amostra completa:

public class CharacterCounter
{

  public static int countOccurrences(String find, String string)
  {
    int count = 0;
    int indexOf = 0;

    while (indexOf > -1)
    {
      indexOf = string.indexOf(find, indexOf + 1);
      if (indexOf > -1)
        count++;
    }

    return count;
  }
}

Ligar:

int occurrences = CharacterCounter.countOccurrences("l", "Hello World.");
System.out.println(occurrences); // 3

Answer #18
import java.util.Scanner;

class apples {

    public static void main(String args[]) {    
        Scanner bucky = new Scanner(System.in);
        String hello = bucky.nextLine();
        int charCount = hello.length() - hello.replaceAll("e", "").length();
        System.out.println(charCount);
    }
}//      COUNTS NUMBER OF "e" CHAR´s within any string input

Answer #19
public static int countOccurrences(String container, String content){
    int lastIndex, currIndex = 0, occurrences = 0;
    while(true) {
        lastIndex = container.indexOf(content, currIndex);
        if(lastIndex == -1) {
            break;
        }
        currIndex = lastIndex + content.length();
        occurrences++;
    }
    return occurrences;
}

Answer #20
String s = "a.b.c.d";
int charCount = s.length() - s.replaceAll("\\.", "").length();

ReplaceAll (".") Substituirá todos os caracteres.

A solução de PhiLho usa ReplaceAll ("[^.]", ""), Que não precisa ser escapada, uma vez que [.] Representa o caractere 'ponto', não 'qualquer caractere'.





string