Existe-t-il un meilleur moyen de se débarrasser des accents et de rendre ces lettres régulières en dehors de l'utilisation de la String.replaceAll()
méthode et du remplacement des lettres une par une? Exemple:
Contribution: orčpžsíáýd
Production: orcpzsiayd
Il n'a pas besoin d'inclure toutes les lettres avec des accents comme l'alphabet russe ou le chinois.
la source
string.replaceAll("\\p{M}", "")
. Voir regular-expressions.info/unicode.html pour plus d'informations.Depuis 2011, vous pouvez utiliser Apache Commons StringUtils.stripAccents (entrée) (depuis 3.0):
Remarque:
La réponse acceptée (celle d'Erick Robertson) ne fonctionne pas pour Ø ou £. Apache Commons 3.5 ne fonctionne pas non plus pour Ø, mais il fonctionne pour Ł. Après avoir lu l'article Wikipedia pour Ø , je ne suis pas sûr qu'il devrait être remplacé par "O": c'est une lettre distincte en norvégien et danois, alphabétisée après "z". C'est un bon exemple des limites de l'approche "strip accents".
la source
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 demandais quelle partie du temps était prise par Normalizer par rapport à l'expression régulière, car la suppression de tous les caractères non ASCII peut se faire sans expression régulière:
De petites accélérations supplémentaires peuvent être obtenues en écrivant dans un char [] et en n'appelant pas toCharArray (), bien que je ne suis pas sûr que la diminution de la clarté du code le mérite:
Cette variation a l'avantage de la justesse de celle qui utilise le normalisateur et d'une partie de la vitesse de celle qui utilise une table. Sur ma machine, celle-ci est environ 4x plus rapide que la réponse acceptée, et 6,6x à 7x plus lente que celle de @ virgo47 (la réponse acceptée est environ 26 fois plus lente que @ virgo47 sur ma machine).
la source
out
doit être redimensionné pour correspondre au nombre de caractères validesj
avant d'être utilisé pour construire l'objet chaîne.flattenToAscii
crée le résultat "aa .." où les points représentent \ u0000. Ce n'est pas bon. La première question est - comment représenter les personnages "non normalisables"? Disons que ce sera?, Ou nous pouvons laisser NULL car là, mais dans tous les cas, nous devons conserver la position correcte de ceux-ci (tout comme la solution regex). Pour cela, le if dans la boucle doit être quelque chose comme:if (c <= '\u007F') out[j++] = c; else if (Character.isLetter(c)) out[j++] = '?';
Il va ralentir un peu, mais il doit être correct en premier lieu. ;-)isLetter
) n'est pas la bonne, mais je n'ai pas trouvé mieux. Je ne suis pas un expert Unicode, donc je ne sais pas comment mieux identifier la classe du caractère unique qui remplace le caractère original. Les lettres fonctionnent bien pour la plupart des applications / utilisations.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 point est d'utiliser
Normalizer
(introduit dans Java 6) au lieu de la table de traduction à l'intérieur de la boucle.Bien que ce ne soit pas une solution "parfaite", cela fonctionne bien lorsque vous connaissez la gamme (dans notre cas Latin1,2), fonctionnait avant Java 6 (ce n'est pas un vrai problème cependant) et est beaucoup plus rapide que la version la plus suggérée (peut ou peut pas un problème):
Les tests sur mon HW avec JDK 32 bits montrent que cela effectue la conversion de àèéľšťč89FDČ à aeelstc89FDC 1 million de fois en ~ 100 ms tandis que le mode Normalizer le fait en 3,7 secondes (37 fois plus lentement). Si vos besoins concernent les performances et que vous connaissez la plage d'entrée, cela peut être pour vous.
Prendre plaisir :-)
la source
travaillé pour moi. La sortie de l'extrait ci-dessus donne "aee" qui est ce que je voulais, mais
n'a fait aucune substitution.
la source
Selon la langue, ceux-ci peuvent ne pas être considérés comme des accents (qui changent le son de la lettre), mais comme des signes diacritiques
https://en.wikipedia.org/wiki/Diacritic#Languages_with_letters_containing_diacritics
"Le bosniaque et le croate portent les symboles č, ć, đ, š et ž, qui sont considérés comme des lettres distinctes et sont répertoriés comme tels dans les dictionnaires et autres contextes dans lesquels les mots sont répertoriés par ordre alphabétique."
Les supprimer peut être intrinsèquement changer le sens du mot, ou changer les lettres en des lettres complètement différentes.
la source
J'ai rencontré le même problème lié à la vérification de l'égalité des chaînes, l'une des chaînes de comparaison a le code de caractère ASCII 128-255 .
Utilisez le code ci-dessous pour différents espaces et leurs codes d'octets:
wiki for List_of_Unicode_characters
Transl Translittérations ASCII de la chaîne Unicode pour Java.
unidecode
➩ en utilisant
Guava
: Google CoreLibraries for Java
.Pour le codage d'URL pour l'espace, utilisez la bibliothèque de goyaves.
➩ Pour surmonter ce problème utilisé
String.replaceAll()
avec certainsRegularExpression
.➩ Utilisation de java.text.Normalizer.Form . Cette énumération fournit des constantes des quatre formulaires de normalisation Unicode qui sont décrits dans l' Annexe 15 de la norme Unicode - Formulaires de normalisation Unicode et deux méthodes pour y accéder.
Test de String et de sorties sur différentes approches comme ➩ Unidecode, Normalizer, StringUtils .
Utiliser Unidecode est le
best choice
, Mon code final illustré ci-dessous.la source
Je suggère Junidecode . Il gérera non seulement «Ł» et «Ø», mais il fonctionne également bien pour la transcription d'autres alphabets, tels que le chinois, en alphabet latin.
la source
La solution @David Conrad est la plus rapide que j'ai essayée en utilisant le Normalizer, mais elle a un bug. Il supprime essentiellement les caractères qui ne sont pas des accents, par exemple les caractères chinois et d'autres lettres comme æ, sont tous supprimés. Les caractères que nous voulons supprimer 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 essentiellement par être combinés dans un autre caractère. Si vous pouvez les voir isolés en tant que personnage, par exemple comme ceci `, je suppose que c'est combiné avec le caractère espace.
la source
L'une des meilleures façons d' utiliser l'expression régulière et le normaliseur si vous n'avez pas de bibliothèque est:
C'est plus efficace que replaceAll ("[^ \ p {ASCII}]", "")) et si vous n'avez pas besoin de signes diacritiques (comme votre exemple).
Sinon, vous devez utiliser le modèle p {ASCII}.
Cordialement.
la source
Je pense que la meilleure solution est de convertir chaque caractère en HEX et de le remplacer par un autre HEX. C'est parce qu'il existe 2 types Unicode:
Par exemple, "Ồ" écrit par Composic Unicode est différent de "Ồ" écrit par Precomposed Unicode. Vous pouvez copier mes exemples de caractères et les convertir pour voir la différence.
J'ai développé cette fonctionnalité pour que certaines banques convertissent les informations avant de les envoyer à la banque principale (ne prennent généralement pas en charge Unicode) et j'ai rencontré ce problème lorsque les utilisateurs finaux utilisent plusieurs types de caractères Unicode pour saisir les données. Je pense donc que la conversion en HEX et son remplacement est le moyen le plus fiable.
la source
Si quelqu'un s'efforce de le faire dans kotlin, ce code fonctionne comme un charme. Pour éviter les incohérences, j'utilise également .toUpperCase et Trim (). alors je jette cette fonction:
}
pour utiliser ces amusants, lancez le code comme ceci:
la source