Есть ли лучший способ избавиться от акцентов и сделать эти буквы регулярными, кроме использования String.replaceAll()
метода и замены букв одна за другой? Пример:
Входные данные: orčpžsíáýd
Вывод: orcpzsiayd
Не нужно включать все буквы с акцентами, как русский алфавит или китайский.
java
string
diacritics
Мартин
источник
источник
string.replaceAll("\\p{M}", "")
. Смотрите регулярно-expressions.info/unicode.html для получения дополнительной информации.Начиная с 2011 года вы можете использовать Apache Commons StringUtils.stripAccents (входная информация) (начиная с версии 3.0):
Примечание:
Принятый ответ (Эрика Робертсона) не работает для Ø или Ł. Apache Commons 3.5 также не работает для Ø, но он работает для Ł. Прочитав статью в Википедии для Ø , я не уверен, что ее следует заменить на «O»: это отдельное письмо на норвежском и датском языках, расположенное в алфавитном порядке после «z». Это хороший пример ограничений подхода «раздевания».
источник
Решение от @ virgo47 очень быстрое, но приблизительное. Принятый ответ использует нормализатор и регулярное выражение. Мне было интересно, какую часть времени занимал Normalizer по сравнению с регулярным выражением, поскольку удаление всех символов, не относящихся к ASCII, может быть выполнено без регулярного выражения:
Небольшие дополнительные ускорения можно получить, записав в char [] и не вызывая toCharArray (), хотя я не уверен, что уменьшение ясности кода заслуживает этого:
Преимущество этого варианта состоит в правильности использования нормализатора и скорости использования таблицы. На моей машине этот примерно в 4 раза быстрее, чем принятый ответ, и в 6,6-7 раз медленнее, чем у @ virgo47 (принятый ответ примерно в 26 раз медленнее, чем у @ virgo47 на моей машине).
источник
out
должен быть изменен, чтобы соответствовать количеству допустимых символов,j
прежде чем он будет использован для создания строкового объекта.flattenToAscii
создает результат "aa ..", где точки представляют \ u0000. Это не хорошо. Первый вопрос - как изобразить «ненормализуемых» персонажей? Допустим, это будет?, Или мы можем оставить там NULL char, но в любом случае мы должны сохранить их правильное положение (как это делает решение регулярных выражений). Для этого условие if в цикле должно быть примерно таким:if (c <= '\u007F') out[j++] = c; else if (Character.isLetter(c)) out[j++] = '?';
оно немного замедлит его, но в первую очередь должно быть правильным. ;-)isLetter
) не правильный, но я не нашел лучшего. Я не эксперт по Unicode, поэтому я не знаю, как лучше определить класс одиночного символа, который заменяет оригинальный символ. Письма работают нормально для большинства приложений / использования.РЕДАКТИРОВАТЬ: Если вы не застряли с Java <6, и скорость не критична и / или таблица перевода слишком ограничена, используйте ответ Дэвида. Смысл в том, чтобы использовать
Normalizer
(представленный в Java 6) вместо таблицы перевода внутри цикла.Хотя это не «идеальное» решение, оно хорошо работает, когда вы знаете диапазон (в нашем случае Latin1,2), работало до Java 6 (хотя это и не является реальной проблемой) и намного быстрее, чем наиболее рекомендуемая версия (может или может не будет проблемой)
Тесты на моем HW с 32-битным JDK показывают, что он выполняет преобразование из файла aeelstc89FDC из aeelstc89FDC 1 миллион раз за ~ 100 мс, в то время как метод нормализатора делает это за 3,7 с (в 37 раз медленнее). Если ваши потребности в производительности и вы знаете диапазон ввода, это может быть для вас.
Наслаждаться :-)
источник
работал на меня. Вывод приведенного выше фрагмента дает «aee», что я и хотел, но
не сделал никакой замены.
источник
В зависимости от языка, они могут рассматриваться не как акценты (которые изменяют звучание буквы), а как диакритические знаки
https://en.wikipedia.org/wiki/Diacritic#Languages_with_letters_containing_diacritics
«Боснийский и хорватский имеют символы č, ć, đ, š и ž, которые считаются отдельными буквами и перечислены как таковые в словарях и других контекстах, в которых слова перечислены в алфавитном порядке».
Удаление их может по своей сути изменить значение слова или заменить буквы на совершенно другие.
источник
Я столкнулся с той же проблемой, связанной с проверкой равенства строк. Одна из сравниваемых строк имеет код символа ASCII 128-255 .
Используйте приведенный ниже код для различных пространств и их байт-кодов:
wiki for List_of_Unicode_characters
SC ASCII транслитерация строки Unicode для Java.
unidecode
➩ используя
Guava
: Google CoreLibraries for Java
.Для кодирования URL для пробела используйте библиотеку Guava.
➩ Чтобы преодолеть эту проблему, используется
String.replaceAll()
с некоторымиRegularExpression
.➩ Использование java.text.Normalizer.Form . Это перечисление предоставляет константы четырех форм нормализации Unicode, которые описаны в Стандартном приложении № 15 к Unicode - Формы нормализации Unicode и два метода для доступа к ним.
Тестирование строки и выводов по различным подходам, таким как ➩ Unidecode, Normalizer, StringUtils .
Использование Unidecode - это
best choice
мой окончательный код, показанный ниже.источник
Я предлагаю Junidecode . Он будет обрабатывать не только «Ł» и «Ø», но также хорошо работает для транскрибирования с других алфавитов, таких как китайский, в латинский алфавит.
источник
Решение @David Conrad - самое быстрое, что я пробовал использовать нормализатор, но в нем есть ошибка. Он в основном удаляет символы, которые не являются ударением, например, китайские и другие буквы, такие как æ, все удаляются. Символы, которые мы хотим вырезать, не являются пробелами, символами, которые не занимают дополнительной ширины в последней строке. Эти символы нулевой ширины в основном объединяются в каком-то другом символе. Если вы видите их изолированными как символы, например, вот так `, я предполагаю, что они объединены с символом пробела.
источник
Один из лучших способов использования регулярных выражений и нормализатора, если у вас нет библиотеки, это:
Это более эффективно, чем replaceAll ("[^ \ p {ASCII}]", "")), и если вам не нужны диакритические знаки (как в вашем примере).
В противном случае вы должны использовать шаблон p {ASCII}.
С уважением.
источник
Я думаю, что лучшее решение - конвертировать каждый символ в HEX и заменить его другим HEX. Это потому, что есть 2 Unicode, набрав:
Например, «Ồ», написанный Composite Unicode, отличается от «Ồ», написанного Precomposed Unicode. Вы можете скопировать мои образцы символов и преобразовать их, чтобы увидеть разницу.
Я разработал эту функцию для некоторых банков, чтобы преобразовать информацию перед отправкой в основной банк (обычно не поддерживающий Юникод), и столкнулся с этой проблемой, когда конечные пользователи используют множественный ввод Юникода для ввода данных. Поэтому я думаю, что переход на HEX и его замена - самый надежный способ.
источник
Если кто-то пытается сделать это в kotlin, этот код работает как шарм. Чтобы избежать несоответствий, я также использую .toUpperCase и Trim (). тогда я разыграю эту функцию:
}
чтобы использовать эти забавы, приведите код так:
источник