Удалить акценты из String
Есть ли какой-либо способ в Android, который (насколько мне известно) не имеет java.text.Normalizer, чтобы удалить любой акцент из String. Например, "éàù" становится "eau".
Я бы хотел, чтобы избежать разбора строки, чтобы проверить каждый символ, если это возможно!
Ответы
Ответ 1
java.text.Normalizer
есть в Android (в последних версиях). Вы можете использовать его.
EDIT Для справки, вот как использовать Normalizer
:
string = Normalizer.normalize(string, Normalizer.Form.NFD);
string = string.replaceAll("[^\\p{ASCII}]", "");
(вставлен по ссылке в комментариях ниже)
Ответ 2
Я настроил решение Rabi на мои нужды, надеюсь, это поможет кому-то:
private static Map<Character, Character> MAP_NORM;
public static String removeAccents(String value)
{
if (MAP_NORM == null || MAP_NORM.size() == 0)
{
MAP_NORM = new HashMap<Character, Character>();
MAP_NORM.put('À', 'A');
MAP_NORM.put('Á', 'A');
MAP_NORM.put('Â', 'A');
MAP_NORM.put('Ã', 'A');
MAP_NORM.put('Ä', 'A');
MAP_NORM.put('È', 'E');
MAP_NORM.put('É', 'E');
MAP_NORM.put('Ê', 'E');
MAP_NORM.put('Ë', 'E');
MAP_NORM.put('Í', 'I');
MAP_NORM.put('Ì', 'I');
MAP_NORM.put('Î', 'I');
MAP_NORM.put('Ï', 'I');
MAP_NORM.put('Ù', 'U');
MAP_NORM.put('Ú', 'U');
MAP_NORM.put('Û', 'U');
MAP_NORM.put('Ü', 'U');
MAP_NORM.put('Ò', 'O');
MAP_NORM.put('Ó', 'O');
MAP_NORM.put('Ô', 'O');
MAP_NORM.put('Õ', 'O');
MAP_NORM.put('Ö', 'O');
MAP_NORM.put('Ñ', 'N');
MAP_NORM.put('Ç', 'C');
MAP_NORM.put('ª', 'A');
MAP_NORM.put('º', 'O');
MAP_NORM.put('§', 'S');
MAP_NORM.put('³', '3');
MAP_NORM.put('²', '2');
MAP_NORM.put('¹', '1');
MAP_NORM.put('à', 'a');
MAP_NORM.put('á', 'a');
MAP_NORM.put('â', 'a');
MAP_NORM.put('ã', 'a');
MAP_NORM.put('ä', 'a');
MAP_NORM.put('è', 'e');
MAP_NORM.put('é', 'e');
MAP_NORM.put('ê', 'e');
MAP_NORM.put('ë', 'e');
MAP_NORM.put('í', 'i');
MAP_NORM.put('ì', 'i');
MAP_NORM.put('î', 'i');
MAP_NORM.put('ï', 'i');
MAP_NORM.put('ù', 'u');
MAP_NORM.put('ú', 'u');
MAP_NORM.put('û', 'u');
MAP_NORM.put('ü', 'u');
MAP_NORM.put('ò', 'o');
MAP_NORM.put('ó', 'o');
MAP_NORM.put('ô', 'o');
MAP_NORM.put('õ', 'o');
MAP_NORM.put('ö', 'o');
MAP_NORM.put('ñ', 'n');
MAP_NORM.put('ç', 'c');
}
if (value == null) {
return "";
}
StringBuilder sb = new StringBuilder(value);
for(int i = 0; i < value.length(); i++) {
Character c = MAP_NORM.get(sb.charAt(i));
if(c != null) {
sb.setCharAt(i, c.charValue());
}
}
return sb.toString();
}
Ответ 3
Это, вероятно, не самое эффективное решение, но оно будет делать трюк, и оно работает во всех версиях Android:
private static Map<Character, Character> MAP_NORM;
static { // Greek characters normalization
MAP_NORM = new HashMap<Character, Character>();
MAP_NORM.put('ά', 'α');
MAP_NORM.put('έ', 'ε');
MAP_NORM.put('ί', 'ι');
MAP_NORM.put('ό', 'ο');
MAP_NORM.put('ύ', 'υ');
MAP_NORM.put('ή', 'η');
MAP_NORM.put('ς', 'σ');
MAP_NORM.put('ώ', 'ω');
MAP_NORM.put('Ά', 'α');
MAP_NORM.put('Έ', 'ε');
MAP_NORM.put('Ί', 'ι');
MAP_NORM.put('Ό', 'ο');
MAP_NORM.put('Ύ', 'υ');
MAP_NORM.put('Ή', 'η');
MAP_NORM.put('Ώ', 'ω');
}
public static String removeAccents(String s) {
if (s == null) {
return null;
}
StringBuilder sb = new StringBuilder(s);
for(int i = 0; i < s.length(); i++) {
Character c = MAP_NORM.get(sb.charAt(i));
if(c != null) {
sb.setCharAt(i, c.charValue());
}
}
return sb.toString();
}
Ответ 4
В то время как ответ Guillaume работает, он удаляет все символы, отличные от ASCII, из строки. Если вы хотите сохранить их, попробуйте этот код (где string
- строка для упрощения):
// Convert input string to decomposed Unicode (NFD) so that the
// diacritical marks used in many European scripts (such as the
// "C WITH CIRCUMFLEX" → ĉ) become separate characters.
// Also use compatibility decomposition (K) so that characters,
// that have the exact same meaning as one or more other
// characters (such as "㎏" → "kg" or "ヒ" → "ヒ"), match when
// comparing them.
string = Normalizer.normalize(string, Normalizer.Form.NFKD);
StringBuilder result = new StringBuilder();
int offset = 0, strLen = string.length();
while(offset < strLen) {
int character = string.codePointAt(offset);
offset += Character.charCount(character);
// Only process characters that are not combining Unicode
// characters. This way all the decomposed diacritical marks
// (and some other not-that-important modifiers), that were
// part of the original string or produced by the NFKD
// normalizer above, disappear.
switch(Character.getType(character)) {
case Character.NON_SPACING_MARK:
case Character.COMBINING_SPACING_MARK:
// Some combining character found
break;
default:
result.appendCodePoint(Character.toLowerCase(character));
}
}
// Since we stripped all combining Unicode characters in the
// previous while-loop there should be no combining character
// remaining in the string and the composed and decomposed
// versions of the string should be equivalent. This also means
// we do not need to convert the string back to composed Unicode
// before returning it.
return result.toString();
Ответ 5
Все символы с акцентом находятся в расширенном наборе символов ASCII с десятичными значениями, превышающими 127. Таким образом, вы можете перечислить все символы в строке, а если значение десятичного символьного символа больше 127, верните его обратно к желаемому эквивалент. Нет никакого простого способа сопоставить акцентированные символы с неактивными аналогами - вам нужно будет сохранить какую-то карту в памяти, чтобы отобразить расширенные десятичные коды обратно к несохраненным символам.