Estoy tratando de hacer un programa que cuente todas las instancias de una letra en una frase ingresada por el usuario. Por ejemplo, la frase "Hola" generará "h: 1", "e: 1", "l: 2", "o: 1" .
Descubrí cómo encontrar y contar todas las letras, excepto "a" . Cuando comparo "a" consigo mismo más de una vez, devuelve un valor diferente cada vez (por lo que la frase "aaaa" me daría a: 1, b: 1, c: 1, d: 1 ) Aquí está el código I' estoy usando:
int[] countLetter = new int[26]; char[] alphabet = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'}; phrase = phrase.toLowerCase(); String a = "a"; for (int i = 0; i<phrase.length(); i++ ) { char count = phrase.charAt(i); if (Character.isLetter(count)) countLetter[a.compareTo(phrase.substring(i))*-1] = countLetter[a.compareTo(phrase.substring(i))*-1] + 1; } for (int i = 0; i<26; i++) { if (countLetter[i]>0) { System.out.println(alphabet[i] + ": " + countLetter[i]); } }No estoy seguro de lo que estoy haciendo mal, entonces, ¿cómo puedo hacer que "a" permanezca igual?
Nunca debe confiar en el valor de retorno exacto de compareTo , a menos que sea 0 . Si desea convertir los caracteres a , b , c , etc. en índices de una matriz, el mejor enfoque es encontrar la diferencia entre ellos a . De esta forma a se traduce a 0 , b a 1 , etc.:
for (int i = 0; i < phrase.length(); i++) { char ch = phrase.charAt(i); if (Character.isLetter(ch)) { countLetter[ch - 'a']++; } }El error en su código se debió a la forma en que compareTo devuelve su resultado. Como dijo Mureinik, "nunca debe confiar en el valor de retorno exacto de compareTo". Voy a tratar de explicar lo que salió mal.
Si dos cadenas son diferentes, entonces tienen caracteres diferentes en algún índice que sea un índice válido para ambas cadenas, o sus longitudes son diferentes, o ambas cosas. Si tienen caracteres diferentes en una o más posiciones de índice, sea k el índice más pequeño. El método compareTo luego devuelve
return str1.charAt(k) - str2.charAt(k);Si no hay una posición de índice en la que difieran, la cadena más corta precede lexicográficamente a la cadena más larga. En este caso, compareTo devuelve la diferencia de las longitudes de las cadenas.
return str1.length() - str2.length();Cuando la frase String es "aaaa", para diferentes valores de 0-4 esto sucede,
//when i = 0 a.compareTo(phrase.substring(i)) //"a".compareTo("aaaaa") //length of "a" - length of "aaaaaa" //which is -4Al multiplicarlo por -1 como lo hiciste, -4 cambió a 4 que es el índice de la letra 'e'. Puede verificar esto para otros valores de i y comprenderá que así es como obtuvo d, c, b y un contador a 1.
Espero haberte ayudado a encontrar tu error. Consulte este enlace para obtener más detalles sobre compareTo () https://www.w3resource.com/java-tutorial/string/string_compareto.php
Sugiero un enfoque diferente, usar un Mapa podría ser una mejor manera de resolver este problema, un mapa puede almacenar 2 cosas <clave, valor> por entrada, por lo que en la clave puede almacenar el carácter de la frase y el número de instancias del carácter como el valor, aquí hay un ejemplo con comentarios:
public static void main(String[] args) { String phrase = "hello"; HashMap<Character, Integer> map = new HashMap<Character, Integer>(); // Define a map, key type character, value type integer phrase = phrase.toLowerCase(); for (int i = 0; i<phrase.length(); i++ ) { // iterate phrase char c = phrase.charAt(i); // get current character if(map.containsKey(c)) // if key already exists in the map map.put(c, map.get(c) + 1); // increment the current value by 1 for this character else // if key doesn't exists in the map yet map.put(c, 1); // add the character with a value of 1 } for (Map.Entry<Character, Integer> entry : map.entrySet()) { // iterate map System.out.println(entry.getKey() + ": " + entry.getValue()); // print key and value } } Entrada: "hello"
Producción:
e: 1 h: 1 l: 2 o: 1 Entrada: "aaaa"
Producción:
a: 4