Repeated letter counter in java

4

I made a method for counting repeated letters that are stored and ordered alphabetically within a list. The method is counting right but the bug is at the time of printing, it printa the letter and the amount of times that appears in the sentence correctly the problem is that it prints the same element in the same amount of times as its counter. >

  

Ex: a: 3 appears 3 times

     

He printa: a: 3               a: 3               a: 3

     

Example used phrase: "See if you get good grades!"

Method:

public void imprimir(){
    for(int i = 0; i < this.mensagem.size(); i++){
        int cont = 0;
        for(int y = 0; y < this.mensagem.size(); y++){
            if(mensagem.get(i) == mensagem.get(y)) cont++;
        }
        System.out.println(mensagem.get(i)+":"+cont);
    }
}  

Result:

! 1 a: 3 a: 3 a: 3 b: 1 e: 1 i: 1 n: 1 o: 2 o: 2 r: 1 s: 3 s: 3 s: 3 t: 2 t: 2 v: 1 ê: 1

    
asked by anonymous 18.09.2017 / 02:36

3 answers

7

Separate operations into two methods, one will count and the other will show , never do one thing, in which case the code first has to scan < > text and go figure out until the result is finished, use structures to store each letter, example :

import java.util.HashMap;
import java.util.Map;
public class JavaApplication3 
{
    public static void main(String[] args) 
    {
        String s = "Vê se tira notas boas!";
        Map<String, Integer> map = contar(s.replace(" ", "").toLowerCase());
        Imprimir(map);
    }

    public static Map<String, Integer> contar(String frase)
    {        
        Map<String, Integer> map = new TreeMap<>();                
        for(char item : frase.toCharArray())
        {
            Integer s = map.get(String.valueOf(item));
            if (s != null)
            {
                map.put(String.valueOf(item), ++s);
            }
            else
            {
                map.put(String.valueOf(item), 1);
            }
        }
        return map;
    }

    public static void Imprimir(Map<String, Integer> items)
    {       
        for(Map.Entry<String, Integer> a : items.entrySet())
        {
            System.out.println(a.getKey() + ": " +  a.getValue());
        }    
    }    
}

An ONLINE sample

18.09.2017 / 03:05
3

You can use Collections of Java in your favor as follows:

public static void main(String[] args) {
  Map<String, Integer> ocorrencias;

  ocorrencias = contar("Vê se tira notas boas!");
  ocorrencias.forEach((chave, valor) -> System.out.print(chave + ":" + valor + " "));
}

private static Map<String, Integer> contar(String frase) {
  Map<String, Integer> resultado = new TreeMap<>(); // TreeMap para manter o Map ordenado pelas chaves
  List<String> ocorrencias;
  Set<String> letras;

  ocorrencias = Arrays.asList(frase.replace(" ", "").split("")); // Transforma a frase em uma lista que facilitará a contagem
  letras = new TreeSet<>(ocorrencias); // Pega as letras sem duplicidade 

  // Percorre o array de letras sem repetição contando as ocorrências
  letras.forEach((String letra) -> {
    resultado.put(letra, Collections.frequency(ocorrencias, letra));
  });

  return resultado;
}

The code above produces:

!:1 V:1 a:3 b:1 e:1 i:1 n:1 o:2 r:1 s:3 t:2 ê:1

TreeSet does not allow duplicate values, and is great for storing letters without repetition. Then a Map is filled with the value counted by the frequency method.

See working at Ideone.com .

Note: Note that your method is case-sensitive and accented as being different letters. If you want to account for occurrences by neglecting accents and case, use a method that performs conversions before counting as follows:

private static Map<String, Integer> contar2(String frase) {
  String normalizado = Normalizer.normalize(frase, Normalizer.Form.NFD);
  String semAcentos = normalizado.replaceAll("\p{InCombiningDiacriticalMarks}+", "");
  frase = semAcentos.toUpperCase();

  return contar(frase);
}

Which produces the following result (using the same% as before):

!:1 A:3 B:1 E:2 I:1 N:1 O:2 R:1 S:3 T:2 V:1
    
18.09.2017 / 19:41
1

This is happening because every time you find a letter, you are counting how many times it appears and prints. In his example, he finds the "a" 3 times, and in 3 times he counts how many he has and prints.

You can create a map and before counting how many times the letter appears, check if it has already been counted. So you leave your code faster too, preventing it from redoing the same job.

    
18.09.2017 / 18:27