¿Cómo cuento el número de ocurrencias de un char en una cadena?


Tengo la cadena

a.b.c.d

Quiero contar las ocurrencias de '."de una manera idiomática, preferiblemente de una sola línea.

(Anteriormente había expresado esta restricción como "sin un bucle", en caso de que se pregunte por qué todos están tratando de responder sin usar un bucle).

 447
Author: Ivar, 2008-11-09

30 answers

Mi 'línea idiomática' para esto es:

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

¿Por qué escribirlo usted mismo cuando ya está en commons lang?

El oneliner de Spring Framework para esto es:

int occurance = StringUtils.countOccurrencesOf("a.b.c.d", ".");
 632
Author: Cowan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-09-21 13:37:10

Qué tal esto. No usa regexp debajo, por lo que debería ser más rápido que algunas de las otras soluciones y no usará un bucle.

int count = line.length() - line.replace(".", "").length();
 892
Author: Andreas Wederbrand,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-01-18 13:17:41

Resumir otra respuesta y lo que sé todas las formas de hacer esto usando un solo trazador:

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

1) Usando Apache Commons

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

2) Usando Spring Framework

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

3) Usando sustitúyase

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

4) Utilizando sustitúyase todo (caso 1)

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

5) Utilizando sustitúyase todo (caso 2)

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

6) Usando dividir

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

7) Usando Java8 (caso 1)

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

8) Usando Java8 (caso 2), puede ser mejor para unicode que el caso 1

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

9) Usando StringTokenizer

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

From comment : Tenga cuidado con el StringTokenizer, para a.b.c.d funcionará pero para a...b.c....d or ...a. b.c.d. o a....b......c.....d... o etc. no funcionará. Simplemente contará . entre caracteres solo una vez

Más información en github

Prueba de rendimiento (usando JMH, mode = AverageTime, score 0.010 mejor entonces 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
 200
Author: Viacheslav Vedenin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-04-18 17:54:51

Tarde o temprano, algo tiene que hacer un bucle. Es mucho más simple para usted escribir el bucle (muy simple) que usar algo como split que es mucho más poderoso de lo que necesita.

Por todos los medios encapsular el bucle en un método separado, por ejemplo,

public static int countOccurrences(String haystack, char needle)
{
    int count = 0;
    for (int i=0; i < haystack.length(); i++)
    {
        if (haystack.charAt(i) == needle)
        {
             count++;
        }
    }
    return count;
}

Entonces usted no necesita tener el bucle en su código principal - pero el bucle tiene que estar allí en alguna parte.

 166
Author: Jon Skeet,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-11-09 14:38:20

Tuve una idea similar a Mladen, pero al contrario...

String s = "a.b.c.d";
int charCount = s.replaceAll("[^.]", "").length();
println(charCount);
 60
Author: PhiLho,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-11-12 21:32:51
String s = "a.b.c.d";
int charCount = s.length() - s.replaceAll("\\.", "").length();

ReplaceAll (".") reemplazaría a todos los caracteres.

La solución de PhiLho utiliza replaceAll("[^.]",""), que no necesita ser escapado, ya que [.] representa el carácter 'dot', no "cualquier carácter".

 35
Author: Mladen Prajdic,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:10:54

Mi solución 'idiomática de una sola línea':

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

No tengo idea de por qué se acepta una solución que utiliza StringUtils.

 26
Author: mlchen850622,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-11-13 19:30:51
String s = "a.b.c.d";
long result = s.chars().filter(ch -> ch == '.').count();
 24
Author: fubo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-07-04 01:24:03

Un ejemplo más corto es

String text = "a.b.c.d";
int count = text.split("\\.",-1).length-1;
 21
Author: Peter Lawrey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-11-29 13:40:01

Aquí hay una solución sin un bucle:

public static int countOccurrences(String haystack, char needle, int i){
    return ((i=haystack.indexOf(needle, i)) == -1)?0:1+countOccurrences(haystack, needle, i+1);}


System.out.println("num of dots is "+countOccurrences("a.b.c.d",'.',0));

Bueno, hay un bucle, pero es invisible :-)

-- Yonatan

 17
Author: Yonatan Maman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-11-09 14:46:28

No me gusta la idea de asignar una nueva cadena para este propósito. Y como la cadena ya tiene una matriz de caracteres en la parte posterior donde almacena su valor, Cadena.charAt() es prácticamente gratis.

for(int i=0;i<s.length();num+=(s.charAt(i++)==delim?1:0))

Hace el truco, sin asignaciones adicionales que necesitan recopilación, en 1 línea o menos, con solo J2SE.

 13
Author: 0xCAFEBABE,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-04-30 07:07:16

Bien, inspirado por la solución de Yonatan, aquí hay una que es puramente recursiva-los únicos métodos de biblioteca utilizados son length() y charAt(), ninguno de los cuales hace ningún bucle:

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

Si la recursión cuenta como bucle depende de la definición exacta que utilices, pero probablemente sea lo más cerca que llegues.

No se si la mayoría de las JVM hacen recursión de cola en estos días... si no, obtendrás el desbordamiento de pila del mismo nombre para cadenas adecuadamente largas, por supuesto.

 12
Author: Jon Skeet,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-11-05 17:10:37

Inspirado en Jon Skeet, una versión sin bucle que no volará tu stack. También es un punto de partida útil si desea utilizar el framework 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);
    }
}

(Descargo de responsabilidad: No probado, no compilado, no sensible.)

Tal vez la mejor manera de escribirlo (de un solo hilo, sin soporte de par sustituto):

public static int countOccurrences(String haystack, char needle) {
    int count = 0;
    for (char c : haystack.toCharArray()) {
        if (c == needle) {
           ++count;
        }
    }
    return count;
}
 11
Author: Tom Hawtin - tackline,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-09-17 12:30:00

No estoy seguro de la eficiencia de esto, pero es el código más corto que podría escribir sin traer libs de terceros:

public static int numberOf(String target, String content)
{
    return (content.split(target).length - 1);
}
 9
Author: KannedFarU,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-08-12 16:50:45

Con java-8 también podría usar flujos para lograr esto. Obviamente hay una iteración detrás de las escenas, ¡pero no tienes que escribirla explícitamente!

public static long countOccurences(String s, char c){
    return s.chars().filter(ch -> ch == c).count();
}

countOccurences("a.b.c.d", '.'); //3
countOccurences("hello world", 'l'); //3
 9
Author: Alexis C.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-05-26 16:39:49

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

Llamada:

int occurrences = CharacterCounter.countOccurrences("l", "Hello World.");
System.out.println(occurrences); // 3
 7
Author: Benny Neugebauer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-03-03 17:54:04

La forma más sencilla de obtener la respuesta es la siguiente:

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);
}
 6
Author: Amar Magar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-17 09:14:13

En caso de que esté utilizando Spring framework, también puede usar la clase "StringUtils". El método sería "countOccurrencesOf".

 5
Author: user496208,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-04-15 20:21:26

También es posible usar reduce en Java 8 para resolver este problema:

int res = "abdsd3$asda$asasdd$sadas".chars().reduce(0, (a, c) -> a + (c == '$' ? 1 : 0));
System.out.println(res);

Salida:

3
 5
Author: gil.fernandes,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-24 14:05:59
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
 4
Author: kassim,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-11-14 23:33:35

Puede usar la función split() en un solo código de línea

int noOccurence=string.split("#").length-1;
 4
Author: user3322553,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-07-22 09:30:27

Mientras que los métodos pueden ocultarlo, no hay manera de contar sin un bucle (o recursión). Sin embargo, desea usar un char[] por razones de rendimiento.

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

Usar replaceAll (que es RE) no suena como la mejor manera de hacerlo.

 3
Author: tcurdt,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-11-09 18:19:50
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;
}
 3
Author: Hardest,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-06-07 15:29:46
String[] parts = text.split(".");
int occurances = parts.length - 1;

" It's a great day at O.S.G. Dallas! "
     -- Famous Last Words

Bueno, es un caso de conocer su Java, especialmente su comprensión fundamental básica de las clases de colección ya disponibles en Java. Si miras a lo largo de toda la publicación aquí, hay casi todo menos la explicación de Stephen Hawking del Origen del Universo, el libro de bolsillo de Darwin sobre la Evolución y la selección del elenco de Star Trek de Gene Roddenberry en cuanto a por qué fueron con William Shatner corto de cómo hacer esto rápida y fácilmente...

... necesito decir ¿más?

 3
Author: Perry Anderson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-07-29 19:41:54

En algún lugar del código, algo tiene que hacer un bucle. La única manera de evitar esto es un desenrollamiento completo del bucle:

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

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


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

...etc, pero entonces usted es el que hace el bucle, manualmente, en el editor de código fuente-en lugar de la computadora que lo ejecutará. Ver el 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
 2
Author: Piskvor,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-11-11 14:39:57

Aquí hay una solución de recursión de estilo ligeramente 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);
}
 2
Author: Stephen Denne,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-03-20 11:25:18

¿Por qué no dividir en el carácter y luego obtener la longitud de la matriz resultante. la longitud de la matriz siempre será el número de instancias + 1. ¿Verdad?

 2
Author: Darryl Price,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-04-28 04:59:44

El siguiente código fuente le dará no.de ocurrencias de una cadena dada en una palabra introducida por el usuario: -

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

    }
}
 2
Author: Shubham,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-05-02 11:17:22
int count = (line.length() - line.replace("str", "").length())/"str".length();
 2
Author: Shaban,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-05-07 12:29:09

Usando Colecciones de Eclipses

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

Si tiene más de un carácter para contar, puede usar un CharBag de la siguiente manera:

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

Nota: Soy un committer para las Colecciones de Eclipse.

 2
Author: Donald Raab,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-06-23 05:40:05