Pregunta

¿Cómo se puede comprobar si una cadena de un carácter es una letra, incluidas las letras con acentos?

Tuve que resolver esto recientemente, así que lo responderé yo mismo, después de que me lo recordara la reciente pregunta de VB6.

¿Fue útil?

Solución 2

Simplemente comprobando si una letra está en A-Z porque eso no incluye letras con acentos o letras en otros alfabetos.

Descubrí que puedes usar la clase de expresión regular para 'letra Unicode', o una de sus variaciones que distinguen entre mayúsculas y minúsculas:

string.matches("\\p{L}"); // Unicode letter
string.matches("\\p{Lu}"); // Unicode upper-case letter

También puedes hacer esto con Personaje clase:

Character.isLetter(character);

pero eso es menos conveniente si necesita verificar más de una letra.

Otros consejos

Character.isLetter() es mucho más rápido que string.matches(), porque string.matches() compila un nuevo patrón cada vez.Incluso almacenando en caché el patrón, creo que isLetter() aún lo superaría.


EDITAR: Me encontré con esto nuevamente y pensé en intentar obtener algunos números reales.Aquí está mi intento de realizar un punto de referencia, verificando los tres métodos (matches() con y sin almacenamiento en caché Pattern, y Character.isLetter()).También me aseguré de que se verificaran tanto los caracteres válidos como los no válidos, para no sesgar las cosas.

import java.util.regex.*;

class TestLetter {
    private static final Pattern ONE_CHAR_PATTERN = Pattern.compile("\\p{L}");
    private static final int NUM_TESTS = 10000000;

    public static void main(String[] args) {
        long start = System.nanoTime();
        int counter = 0;
        for (int i = 0; i < NUM_TESTS; i++) {
            if (testMatches(Character.toString((char) (i % 128))))
                counter++;
        }
        System.out.println(NUM_TESTS + " tests of Pattern.matches() took " +
                (System.nanoTime()-start) + " ns.");
        System.out.println("There were " + counter + "/" + NUM_TESTS +
                " valid characters");
        /*********************************/
        start = System.nanoTime();
        counter = 0;
        for (int i = 0; i < NUM_TESTS; i++) {
            if (testCharacter(Character.toString((char) (i % 128))))
                counter++;
        }
        System.out.println(NUM_TESTS + " tests of isLetter() took " +
                (System.nanoTime()-start) + " ns.");
        System.out.println("There were " + counter + "/" + NUM_TESTS +
                " valid characters");
        /*********************************/
        start = System.nanoTime();
        counter = 0;
        for (int i = 0; i < NUM_TESTS; i++) {
            if (testMatchesNoCache(Character.toString((char) (i % 128))))
                counter++;
        }
        System.out.println(NUM_TESTS + " tests of String.matches() took " +
                (System.nanoTime()-start) + " ns.");
        System.out.println("There were " + counter + "/" + NUM_TESTS +
                " valid characters");
    }

    private static boolean testMatches(final String c) {
        return ONE_CHAR_PATTERN.matcher(c).matches();
    }
    private static boolean testMatchesNoCache(final String c) {
        return c.matches("\\p{L}");
    }
    private static boolean testCharacter(final String c) {
        return Character.isLetter(c.charAt(0));
    }
}

Y mi salida:

10000000 tests of Pattern.matches() took 4325146672 ns.
There were 4062500/10000000 valid characters
10000000 tests of isLetter() took 546031201 ns.
There were 4062500/10000000 valid characters
10000000 tests of String.matches() took 11900205444 ns.
There were 4062500/10000000 valid characters

Eso es casi 8 veces mejor, incluso con un caché Pattern.(Y sin caché es casi 3 veces peor que con caché).

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top