1
votes

Existe-t-il un moyen plus efficace de compter le nombre de fois où chaque lettre consécutive apparaît dans une chaîne? (Java)

Je crée une méthode qui prend une chaîne spécifiée et compte le nombre de fois où chaque lettre consécutive apparaît.
Par exemple: encoder ("aabbcc"); devrait donner la sortie 2 2 2, car il y a 2 lettres apparaissant dans l'ordre

Mon code était:

for(int i=0;i<word.length()-1;i++) {
    int count=1;

    if(i!=word.length()-1) {
        //System.out.println(word.charAt(i));
        //System.out.println(word.charAt(i+1));
        try {
            while(word.charAt(i)==word.charAt(i+1)) {
                count++;
                i++;
            }
        } catch (Exception e) {}

        System.out.print(count+" ");
    }
}

Mais il n'arrêtait pas de me donner une IndexOutOfBoundsException code> donc je viens d'ajouter un bloc try and catch mais je sais qu'il existe un meilleur moyen


1 commentaires

Cette ligne catch (Exception e) {} n'est généralement pas une bonne chose à faire. Je supprimerais cette capture d'essai et corrigerais toutes les exceptions avec un flux d'application approprié.


7 Réponses :


1
votes

Ne regardez pas en avant comme ceci word.charAt (i) == word.charAt (i + 1) car cela vous donne l'erreur. Au lieu de cela, vérifiez si la lettre à l'index i est la même que la lettre de l'itération précédente - et si c'est le cas - incrémentez le compteur.


0 commentaires

0
votes

Bienvenue dans SO. En général, si vous recevez une exception, vous devez déterminer pourquoi plutôt que d'ajouter une capture.

Une solution plus simple serait:

Deque<Integer> counts = new LinkedList<>();
for (int i = 0; i < word.length(); i++) {
    if (i > 0 && word.charAt(i) == word.charAt(i - 1))
        counts.addLast(count.removeLast() + 1);
    else
        counts.addLast(1);
}


0 commentaires

0
votes

À la fin de la boucle, i + 1 est hors limites.

Vous pouvez les compter comme ceci:

if(i > 0 && word.charAt(i) == word.charAt(i - 1))


0 commentaires

0
votes

Vous pouvez tester que i + 1 est inférieur à word.length () dans votre condition de boucle while . Vous pouvez également enregistrer word.length () dans une variable locale. Comme,

int len = word.length();
for (int i = 0; i < len - 1; i++) {
    int count = 1;
    while (i + 1 < len && word.charAt(i) == word.charAt(i + 1)) {
        count++;
        i++;
    }
    System.out.print(count + " ");
}


0 commentaires

1
votes

Une autre approche serait d'utiliser regex.

String str = "aabbccxa";
String result = Pattern.compile("(?<=(.))(?!\\1)")
                       .splitAsStream(str)
                       .map(e -> String.valueOf(e.length()))
                       .collect(Collectors.joining(" "));
System.out.println(result);

Comment ça marche:

  • diviser la chaîne en groupes de mêmes caractères
  • mappez chaque groupe à sa longueur
  • collecter en utilisant l'espace comme délimiteur

Je pense que c'est une question de goût si c'est mieux que les autres réponses. Plus efficace qu'une simple boucle? Je pense que cela dépend aussi de l'entrée.


0 commentaires

0
votes
char=a, occurance=2
char=b, occurance=3
char=c, occurance=2
char=a, occurance=4

0 commentaires

0
votes

Vous pouvez les rassembler sur une carte et les imprimer. Cela imprime les chaînes réelles qui correspondent au décompte, mais il peut facilement être personnalisé comme vous le souhaitez.

      String str = "aabbbbcccccdddddaaaaz";

      Map<Integer, List<String>> freq = Arrays.stream(
            str.replaceAll("(([a-z])\\2*)", "$1,").split(",")).filter(
                  a -> a.length() > 1).collect(
                        Collectors.groupingBy(String::length));

      freq.forEach((k, v) -> System.out.println(k + " : " + v));

imprime ce qui suit.

2: [aa]
4: [bbbb, aaaa]
5: [ccccc, ddddd]


0 commentaires