pessoal,
com oper. ternário como faço pra saber se a string que entrou é número ou letra?
pessoal,
com oper. ternário como faço pra saber se a string que entrou é número ou letra?
Consegui pensar nesta possibilidade:
import java.util.regex.Pattern;
public class App {
private static String eNumeroOuLetra(String numeroOuLetra) {
return Pattern.matches("[0-9]+", numeroOuLetra) ? "É número" : "É letra";
}
public static void main(String... args) {
System.out.println(eNumeroOuLetra("abc"));
System.out.println(eNumeroOuLetra("123"));
}
}
obrigadaaa!
Outra forma:
private static String eNumeroOuLetra(String numeroOuLetra) {
return numeroOuLetra.matches("[0-9]+") ? "É número" : "É letra";
}
Na verdade é um pouco mais complicado que isso. As soluções acima verificam se só contém números, e se tiver qualquer coisa diferente disso, é considerado “letra”. Se a string for, por exemplo, "%^."
, vai dizer que é letra. Se for "123a"
, também vai dizer que é letra - aliás, nesse caso faz o que?
Enfim, para tratar todos os casos, teria que fazer um pouco diferente (inclusive, “forçar” o uso de operador ternário nem me parece a melhor opção, mas enfim).
Uma opção é ver o primeiro caractere: se for número, eu vejo se o restante é número. Se for letra, eu vejo se o restante é letra. Se não for nem número nem letra, nem preciso ver o resto. E se no meio eu encontro um caractere que não é do mesmo tipo do primeiro, também não preciso ver o resto:
private static String somenteNumerosOuLetras(String str) {
if (str.length() == 0) { // string vazia, nem preciso ver
return "Não tem somente números nem somente letras";
}
char primeiro = str.charAt(0);
Predicate<Character> condicao = null;
String retorno = null;
if (Character.isDigit(primeiro)) { // se o primeiro é número, eu testo se os demais são números
condicao = Character::isDigit;
retorno = "somente dígitos";
} else if (Character.isLetter(primeiro)) { // se o primeiro é letra, eu testo se os demais são letras
condicao = Character::isLetter;
retorno = "somente letras";
}
// se o primeiro não é número nem letra, posso parar aqui
if (condicao == null) {
return "Não tem somente números nem somente letras";
}
// percorro do segundo caractere em diante, vendo se são do mesmo tipo do primeiro
for (int i = 1; i < str.length(); i++) {
char c = str.charAt(i);
if (! condicao.test(c)) { // não é do mesmo tipo, pode retornar (nem preciso ver o resto)
return "Não tem somente números nem somente letras";
}
}
// se chegou aqui é porque todos os caracteres são do mesmo tipo
return retorno;
}
Testando:
System.out.println(somenteNumerosOuLetras("123")); // somente dígitos
System.out.println(somenteNumerosOuLetras("abc")); // somente letras
System.out.println(somenteNumerosOuLetras("123abc")); // Não tem somente números nem somente letras
System.out.println(somenteNumerosOuLetras("@#$%")); // Não tem somente números nem somente letras
Claro que o código ficou “maior”, mas não necessariamente isso é pior. Usar regex, apesar de deixar o código mais curto, é mais lento (claro que para poucas strings pequenas a diferença é imperceptível, mas para grandes quantidades e/ou strings maiores isso pode começar a fazer diferença).
De qualquer forma, como agora são duas condições, com regex teria que fazer dois ternários aninhados:
private static String somenteNumerosOuLetras(String str) {
return str.matches("[0-9]+")
? "somente dígitos"
: ( str.matches("[a-zA-Z]+")
? "somente letras"
: "Não tem somente números nem somente letras" );
}
Um detalhe é que [a-zA-Z]+
não aceita letras acentuadas, mas se quiser pode trocar para str.matches("\\p{L}+")
, que pega qualquer letra definida pelo Unicode (incluindo outros alfabetos, como árabe, japonês, cirílico, etc). Ou ainda str.matches("\\p{IsLatin}+")
, se quiser apenas as letras do nosso alfabeto. Já o primeiro código não precisa de modificação, pois Character.isLetter
já considera qualquer letra Unicode.
Vale lembrar também que cada regex percorre a string uma vez, portanto no pior caso ela será percorrida duas vezes. E novamente, para poucas strings pequenas não faz diferença, mas é importante saber as implicações de cada linha de código que você escreve, e não escolher algo somente porque “é mais curto”.
Será que essa forma também seria válida?
public class Main {
public static void main(String[] args) throws Exception {
System.out.println(check("aaa"));
System.out.println(check("123"));
System.out.println(check("a2c"));
System.out.println(check("!@#"));
System.out.println(check("-+."));
System.out.println(check("-10"));
System.out.println(check("000"));
}
private static String check(String texto) {
boolean isLetras = texto.codePoints()
.allMatch(c -> (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'));
boolean isNumeros = texto.codePoints()
.allMatch(c -> c >= '0' && c <= '9');
return (isLetras) ? "são letras" : (isNumeros) ? "são números" : "nem tudo letra nem tudo número";
}
}