311 votes

Y a-t-il un moyen de se débarrasser des accents et de convertir une chaîne entière en lettres régulières?

Existe-t-il une meilleure façon de se débarrasser des accents et de rendre ces lettres régulières en dehors de la méthode String.replaceAll() et de remplacer les lettres une par une? Exemple:

Entrée: orčpžsíáýd

Sortie: orcpzsiayd

Il n'a pas besoin d'inclure toutes les lettres avec des accents comme l'alphabet russe ou le chinois.

444voto

Erick Robertson Points 12958

Utiliser java.text.Normalizer qui s'en occupera pour vous.

string = Normalisateur.normaliser(string, Normalisateur.Forme.NFD);

Cela permettra de séparer toutes les marques d'accent sur les personnages. Ensuite, il vous suffit de comparer chaque caractère contre une lettre et jetez celles qui ne le sont pas.

string = string.replaceAll("[^\\p{ASCII}]", "");

Si votre texte est en unicode, vous devez utiliser ceci à la place:

string = string.replaceAll("\\p{M}", "");

Pour l'unicode, \\P{M} correspond à la base de glyphe et \\p{M} (en minuscules) qui correspond à chaque accent.

Grâce à GarretWilson pour le pointeur et regular-expressions.info pour la grande unicode guide.

64voto

David Conrad Points 3529

La solution par @virgo47 est très rapide, mais approximatif. L'on a accepté la réponse utilise Normalisateur et une expression régulière. Je me demandais ce qu'une partie du temps a été pris par le Normalisateur rapport à l'expression régulière, depuis la suppression de tous les caractères non-ASCII peut être fait sans une regex:

import java.text.Normalizer;

public class Strip {
    public static String flattenToAscii(String string) {
        StringBuilder sb = new StringBuilder(string.length());
        string = Normalizer.normalize(string, Normalizer.Form.NFD);
        for (char c : string.toCharArray()) {
            if (c <= '\u007F') sb.append(c);
        }
        return sb.toString();
    }
}

Petit speed-ups peuvent être obtenus par écrit dans un char[] et ne pas appeler toCharArray(), bien que je ne suis pas sûr que la diminution dans le code de la clarté des mérites qu'elle:

public static String flattenToAscii(String string) {
    char[] out = new char[string.length()];
    string = Normalizer.normalize(string, Normalizer.Form.NFD);
    int j = 0;
    for (int i = 0, n = string.length(); i < n; ++i) {
        char c = string.charAt(i);
        if (c <= '\u007F') out[j++] = c;
    }
    return new String(out);
}

Cette variante a l'avantage de la justesse de l'une à l'aide de Normalisateur et certains de la vitesse de l'un à l'aide d'un tableau. Sur ma machine, celui-ci est d'environ 4x plus rapide que la accepté de répondre, et de 6,6 x à 7 fois plus lent que @virgo47 (accepté la réponse est sur le 26x plus lent que @virgo47 sur ma machine).

33voto

virgo47 Points 916

Si ce n'est pas "parfait" solution, il fonctionne bien quand vous savez que la gamme (dans notre cas, Latin1,2), a travaillé avant de Java 6 (pas un vrai problème), et est beaucoup plus rapide que la plupart suggéré version (peut ou peut ne pas être un problème):

    /**
 * Mirror of the unicode table from 00c0 to 017f without diacritics.
 */
private static final String tab00c0 = "AAAAAAACEEEEIIII" +
    "DNOOOOO\u00d7\u00d8UUUUYI\u00df" +
    "aaaaaaaceeeeiiii" +
    "\u00f0nooooo\u00f7\u00f8uuuuy\u00fey" +
    "AaAaAaCcCcCcCcDd" +
    "DdEeEeEeEeEeGgGg" +
    "GgGgHhHhIiIiIiIi" +
    "IiJjJjKkkLlLlLlL" +
    "lLlNnNnNnnNnOoOo" +
    "OoOoRrRrRrSsSsSs" +
    "SsTtTtTtUuUuUuUu" +
    "UuUuWwYyYZzZzZzF";

/**
 * Returns string without diacritics - 7 bit approximation.
 *
 * @param source string to convert
 * @return corresponding string without diacritics
 */
public static String removeDiacritic(String source) {
    char[] vysl = new char[source.length()];
    char one;
    for (int i = 0; i < source.length(); i++) {
        one = source.charAt(i);
        if (one >= '\u00c0' && one <= '\u017f') {
            one = tab00c0.charAt((int) one - '\u00c0');
        }
        vysl[i] = one;
    }
    return new String(vysl);
}

Des Tests sur mon HW avec 32 bits JDK montrer que ce n'effectue la conversion de àèéľšťč89FDČ à aeelstc89FDC 1 million de fois dans le ~100ms tout Normalisateur, on en 3,7 s (37x plus lent). Dans le cas où vos besoins sont autour de la performance et vous connaissez la plage d'entrée, ce peut être pour vous.

Profiter :-)

27voto

Nico Points 76
<pre><code></code><p><pre><code></code></pre><p></pre>

6voto

NinjaCat Points 3809

En fonction de la langue, celles-ci pourraient ne pas être considérés comme des accents (qui modifient le son de la lettre), mais les signes diacritiques

https://secure.wikimedia.org/wikipedia/en/wiki/Diacritic#Languages_with_letters_containing_diacritics

"Bosniaques et croates ont les symboles è, æ, î, i et ž, qui sont considérés comme des lettres distinctes et sont répertoriés comme tels dans les dictionnaires et dans d'autres contextes dans lesquels les mots sont classés selon l'ordre alphabétique."

Leur suppression pourrait être fondamentalement changer la signification de la parole, ou de changer les lettres de complètement différent.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X