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 un meilleur moyen de se débarrasser des accents et de rendre ces lettres régulières en dehors de la méthode Ssortingng.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.

Utilisez java.text.Normalizer pour gérer cela pour vous.

 ssortingng = Normalizer.normalize (chaîne, Normalizer.Form.NFD);

Cela séparera toutes les marques d’accent des caractères. Ensuite, il vous suffit de comparer chaque caractère avec une lettre et de rejeter ceux qui ne le sont pas.

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

Si votre texte est en Unicode, vous devriez plutôt l’utiliser:

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

Pour unicode, \\P{M} correspond au glyphe de base et \\p{M} (minuscule) correspond à chaque accent.

Merci à GarretWilson pour le pointeur et regular-expressions.info pour le grand guide Unicode.

En 2011, vous pouvez utiliser Apache Commons SsortingngUtils.ssortingpAccents (input) (depuis la version 3.0):

  Ssortingng input = SsortingngUtils.ssortingpAccents("Tĥïŝ ĩš â fůňķŷ Šťŕĭńġ"); System.out.println(input); // Prints "This is a funky Ssortingng" 

Remarque:

La réponse acceptée (Erick Robertson) ne fonctionne pas pour Ø ou Ł. Apache Commons 3.5 ne fonctionne pas non plus pour Ø, mais cela fonctionne pour £. Après avoir lu l’article de Wikipedia pour Ø , je ne suis pas sûr qu’il devrait être remplacé par “O”: c’est une lettre séparée en norvégien et en danois, classée par ordre alphabétique après “z”. C’est un bon exemple des limites de l’approche “ssortingp accents”.

La solution de @ virgo47 est très rapide, mais approximative. La réponse acceptée utilise Normalizer et une expression régulière. Je me suis demandé quelle partie du temps avait été prise par Normalizer par rapport à l’expression régulière, car la suppression de tous les caractères non-ASCII peut être effectuée sans regex:

 import java.text.Normalizer; public class Ssortingp { public static Ssortingng flattenToAscii(Ssortingng ssortingng) { SsortingngBuilder sb = new SsortingngBuilder(ssortingng.length()); ssortingng = Normalizer.normalize(ssortingng, Normalizer.Form.NFD); for (char c : ssortingng.toCharArray()) { if (c <= '\u007F') sb.append(c); } return sb.toString(); } } 

De petites accélérations supplémentaires peuvent être obtenues en écrivant dans un caractère char [] et en n'appelant pas toCharArray (), même si je ne suis pas certain que la diminution de la clarté du code le justifie:

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

Cette variation a l'avantage de l'exactitude de celle utilisant Normalizer et de la vitesse de celle utilisant un tableau. Sur ma machine, celle-ci est environ 4 fois plus rapide que la réponse acceptée et 6,6 à 7 fois plus lente que celle de @ virgo47 (la réponse acceptée est environ 26 fois plus lente que celle de @ virgo47 sur ma machine).

EDIT: Si vous n’êtes pas coincé avec Java <6 et que la vitesse n'est pas critique et / ou que la table de traduction est trop limitative, utilisez la réponse de David. Le but est d'utiliser Normalizer (introduit dans Java 6) au lieu de la table de traduction dans la boucle.

Bien que ce ne soit pas une solution “parfaite”, elle fonctionne bien lorsque vous connaissez la plage (dans notre cas Latin1,2), fonctionne avant Java 6 (pas un problème réel) et est beaucoup plus rapide que la version la plus suggérée (mai ou ne pas être un problème):

  /** * Mirror of the unicode table from 00c0 to 017f without diacritics. */ private static final Ssortingng tab00c0 = "AAAAAAACEEEEIIII" + "DNOOOOO\u00d7\u00d8UUUUYI\u00df" + "aaaaaaaceeeeiiii" + "\u00f0nooooo\u00f7\u00f8uuuuy\u00fey" + "AaAaAaCcCcCcCcDd" + "DdEeEeEeEeEeGgGg" + "GgGgHhHhIiIiIiIi" + "IiJjJjKkkLlLlLlL" + "lLlNnNnNnnNnOoOo" + "OoOoRrRrRrSsSsSs" + "SsTtTtTtUuUuUuUu" + "UuUuWwYyYZzZzZzF"; /** * Returns ssortingng without diacritics - 7 bit approximation. * * @param source ssortingng to convert * @return corresponding ssortingng without diacritics */ public static Ssortingng removeDiacritic(Ssortingng 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); } 

Les tests effectués sur mon matériel avec le JDK 32 bits montrent que cette méthode permet de convertir un million de fois de aèé inš àč89FDČ à aeelstc89FDC en ~ 100ms alors que le mode Normalizer le fait en 3.7s (37x plus lent). Si vos besoins sont liés aux performances et que vous connaissez la plage de saisie, cela peut être pour vous.

Prendre plaisir 🙂

 System.out.println(Normalizer.normalize("àèé", Normalizer.Form.NFD).replaceAll("\\p{InCombiningDiacriticalMarks}+", "")); 

travaillé pour moi La sortie de l’extrait ci-dessus donne “aee” qui est ce que je voulais, mais

 System.out.println(Normalizer.normalize("àèé", Normalizer.Form.NFD).replaceAll("[^\\p{ASCII}]", "")); 

n’a fait aucune substitution.

Selon la langue, ceux-ci peuvent ne pas être considérés comme des accents (qui changent le son de la lettre), mais des signes diacritiques

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

“Le bosniaque et le croate ont les symboles č, ć, đ, š et ž, qui sont considérés comme des lettres séparées et sont répertoriés en tant que tels dans les dictionnaires et autres contextes dans lesquels les mots sont classés par ordre alphabétique.”

Les supprimer peut changer de manière inhérente le sens du mot ou changer les lettres en des termes complètement différents.

La solution @David Conrad est la plus rapide avec laquelle j’ai essayé d’utiliser Normizer, mais elle a un bogue. Il dépouille essentiellement les caractères qui ne sont pas des accents, par exemple les caractères chinois et les autres lettres comme æ, sont tous dépouillés. Les caractères que nous voulons dépouiller sont des marques sans espacement, des caractères qui ne prennent pas de largeur supplémentaire dans la chaîne finale. Ces caractères de largeur nulle finissent par se combiner dans un autre caractère. Si vous pouvez les voir isolés comme un personnage, par exemple comme ceci `, je suppose que c’est combiné avec le caractère d’espace.

 public static Ssortingng flattenToAscii(Ssortingng ssortingng) { char[] out = new char[ssortingng.length()]; Ssortingng norm = Normalizer.normalize(ssortingng, Normalizer.Form.NFD); int j = 0; for (int i = 0, n = norm.length(); i < n; ++i) { char c = norm.charAt(i); int type = Character.getType(c); //Log.d(TAG,""+c); //by Ricardo, modified the character check for accents, ref: http://stackoverflow.com/a/5697575/689223 if (type != Character.NON_SPACING_MARK){ out[j] = c; j++; } } //Log.d(TAG,"normalized string:"+norm+"/"+new String(out)); return new String(out); } 

J’ai rencontré le même problème lié à la vérification de l’égalité des chaînes, une des chaînes de comparaison ayant le code de caractères ASCII 128-255 .

c.-à-d. espace insécable – [Hex – A0] Espace [Hex – 20]. Pour montrer un espace sans rupture par rapport au HTML. J’ai utilisé les spacing entities suivantes. Leur caractère et ses octets sont comme &emsp is very wide space[ ]{-30, -128, -125}, &ensp is somewhat wide space[ ]{-30, -128, -126}, &thinsp is narrow space[ ]{32} , Non HTML Space {}

 Ssortingng s1 = "My Sample Space Data", s2 = "My Sample Space Data"; System.out.format("S1: %s\n", java.util.Arrays.toSsortingng(s1.getBytes())); System.out.format("S2: %s\n", java.util.Arrays.toSsortingng(s2.getBytes())); 

Sortie en octets:

S1: [77, 121, 32 , 83, 97, 109, 112, 108, 101, 32 , 83, 112, 97, 99, 101, 32 , 68, 97, 116, 97] S2: [77, 121, -30, -128, -125 , 83, 97, 109, 112, 108, 101, -30, -128, -125 , 83, 112, 97, 99, 101, -30, -128, -125 , 68 , 97, 116, 97]

Utilisez le code ci-dessous pour les différents espaces et leurs codes d’octets: wiki for List_of_Unicode_characters

 Ssortingng spacing_entities = "very wide space,narrow space,regular space,invisible separator"; System.out.println("Space Ssortingng :"+ spacing_entities); byte[] byteArray = // spacing_entities.getBytes( Charset.forName("UTF-8") ); // Charset.forName("UTF-8").encode( s2 ).array(); {-30, -128, -125, 44, -30, -128, -126, 44, 32, 44, -62, -96}; System.out.println("Bytes:"+ Arrays.toSsortingng( byteArray ) ); try { System.out.format("Bytes to Ssortingng[%S] \n ", new Ssortingng(byteArray, "UTF-8")); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } 
  • ➩ Translittérations ASCII de la chaîne Unicode pour Java. unidecode

     Ssortingng initials = Unidecode.decode( s2 ); 
  • ➩ utilisation de Guava : Libraries for Java Google Core Libraries for Java .

     Ssortingng replaceFrom = CharMatcher.WHITESPACE.replaceFrom( s2, " " ); 

    Pour le codage URL pour l’espace, utilisez la bibliothèque Guava.

     Ssortingng encodedSsortingng = UrlEscapers.urlFragmentEscaper().escape(inputSsortingng); 
  • Overcome Pour surmonter ce problème, utilisez Ssortingng.replaceAll() avec un RegularExpression .

     // \p{Z} or \p{Separator}: any kind of whitespace or invisible separator. s2 = s2.replaceAll("\\p{Zs}", " "); s2 = s2.replaceAll("[^\\p{ASCII}]", " "); s2 = s2.replaceAll(" ", " "); 
  • ➩ Utilisation de java.text.Normalizer.Form . Cette énumération fournit les constantes des quatre formulaires de normalisation Unicode décrits dans l’ Annexe 15 de la norme Unicode – Formulaires de normalisation Unicode et deux méthodes pour y accéder.

    entrer la description de l'image ici

     s2 = Normalizer.normalize(s2, Normalizer.Form.NFKC); 

Test de la chaîne et des sorties sur différentes approches telles que id Unidecode, Normalizer, SsortingngUtils .

 Ssortingng strUni = "Tĥïŝ ĩš â fůňķŷ Šťŕĭńġ Æ,Ø,Ð,ß"; // This is a funky Ssortingng AE,O,D,ss Ssortingng initials = Unidecode.decode( strUni ); // Following Produce this o/p: Tĥïŝ ĩš â fůňķŷ Šťŕĭńġ Æ,Ø,Ð,ß Ssortingng temp = Normalizer.normalize(strUni, Normalizer.Form.NFD); Pattern pattern = Pattern.comstack("\\p{InCombiningDiacriticalMarks}+"); temp = pattern.matcher(temp).replaceAll(""); Ssortingng input = org.apache.commons.lang3.SsortingngUtils.ssortingpAccents( strUni ); 

Utiliser Unidecode est le best choice , Mon code final est indiqué ci-dessous.

 public static void main(Ssortingng[] args) { Ssortingng s1 = "My Sample Space Data", s2 = "My Sample Space Data"; Ssortingng initials = Unidecode.decode( s2 ); if( s1.equals(s2)) { //[ , ] %A0 - %2C - %20 « http://www.ascii-code.com/ System.out.println("Equal Unicode Ssortingngs"); } else if( s1.equals( initials ) ) { System.out.println("Equal Non Unicode Ssortingngs"); } else { System.out.println("Not Equal"); } } 

Je suggère Junidecode . Il ne traitera pas seulement “Ł” et “Ø”, mais il fonctionnera également bien pour transcrire d’autres alphabets, tels que le chinois, dans l’alphabet latin.