Domanda

Come si verifica se una stringa di un carattere è una lettera, comprese eventuali lettere con accenti?

Ho dovuto risolverlo di recente, quindi risponderò da solo, dopo che me lo ha ricordato la recente domanda su VB6.

È stato utile?

Soluzione 2

Sto solo controllando se una lettera è in A-Z perché non include lettere con accenti o lettere in altri alfabeti.

Ho scoperto che puoi utilizzare la classe delle espressioni regolari per "Lettera Unicode" o una delle sue varianti con distinzione tra maiuscole e minuscole:

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

Puoi farlo anche con Carattere classe:

Character.isLetter(character);

ma è meno conveniente se devi controllare più di una lettera.

Altri suggerimenti

Character.isLetter() è molto più veloce di string.matches(), perché string.matches() compila ogni volta un nuovo Pattern.Anche memorizzando nella cache il pattern, penso che isLetter() lo batterebbe comunque.


MODIFICARE: Mi sono imbattuto di nuovo in questo e ho pensato di provare a trovare dei numeri reali.Ecco il mio tentativo di benchmark, controllando tutti e tre i metodi (matches() con e senza memorizzazione nella cache di Pattern, E Character.isLetter()).Mi sono anche assicurato che fossero controllati sia i caratteri validi che quelli non validi, in modo da non distorcere le cose.

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));
    }
}

E il mio risultato:

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

Quindi è quasi 8 volte migliore, anche con un file cache Pattern.(E senza cache è quasi 3 volte peggio di quanto memorizzato nella cache.)

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top