Преобразование символов, букв Accent в английский алфавит

Я делаю это так:

Date oneWeekAgo = DateUtils.addDays(DateUtils.truncate(new Date(), java.util.Calendar.DAY_OF_MONTH), -7);
126
задан Andreas Petersson 9 September 2009 в 08:39
поделиться

7 ответов

Повторная публикация моего сообщения из Как удалить диакритические знаки (диакритические знаки) из строки в .NET?

Этот метод отлично работает в java (исключительно для целей удаление диакритических знаков или акцентов) .

Он в основном преобразует все символы с диакритическими знаками в их деакцентированные аналоги с последующим их объединением диакритических знаков. Теперь вы можете использовать регулярное выражение для удаления диакритических знаков.

import java.text.Normalizer;
import java.util.regex.Pattern;

public String deAccent(String str) {
    String nfdNormalizedString = Normalizer.normalize(str, Normalizer.Form.NFD); 
    Pattern pattern = Pattern.compile("\\p{InCombiningDiacriticalMarks}+");
    return pattern.matcher(nfdNormalizedString).replaceAll("");
}
194
ответ дан 24 November 2019 в 00:50
поделиться

Попытка «преобразовать их всех» - неправильный подход к проблеме.

Во-первых, вам нужно понимать ограничения того, что вы пытаетесь сделать. Как отмечали другие, диакритические знаки существуют по какой-то причине: они, по сути, являются уникальными буквами в алфавите этого языка со своим собственным значением / звуком и т. Д.: Удаление этих знаков аналогично замене случайных букв в английском слове. Это еще до того, как вы даже перейдете к рассмотрению кириллических языков и других текстов, основанных на алфавите, таких как арабский, которые просто невозможно «преобразовать» в английский.

Если вы должны по какой-либо причине преобразовать символы, Тогда единственный разумный способ подойти к этому - сначала уменьшить объем поставленной задачи. Рассмотрим источник ввода - если вы пишете приложение для «западного мира» (чтобы использовать такую ​​же хорошую фразу, как любая другая), маловероятно, что вам когда-либо понадобится разбирать арабские символы. Точно так же набор символов Unicode содержит сотни математических и графических символов: у пользователей нет (простого) способа напрямую ввести их, поэтому вы можете предположить, что их можно игнорировать.

Выполнив эти логические шаги, вы можете уменьшить количество возможных символов для синтаксического анализа до точки, где возможна операция поиска / замены на основе словаря. Тогда создание словарей превращается в небольшую скучную работу, а выполнение замены - в тривиальную задачу. Если ваш язык поддерживает собственные символы Unicode (как это делает Java) и правильно оптимизирует статические структуры, такой поиск и замена имеют тенденцию быть ослепительно быстрыми.

Это связано с опытом работы над приложением, которое требовалось, чтобы конечные пользователи могли выполнять поиск в библиографических данных, содержащих диакритические символы. Для создания поисковых массивов (как это было в нашем случае) потребовалось около 1 человеко-дня, чтобы охватить все диакритические знаки для всех западноевропейских языков.

19
ответ дан 24 November 2019 в 00:50
поделиться

Если необходимо преобразовать «òéışöç-> oeisoc», вы можете использовать это в качестве отправной точки:

public class AsciiUtils {
    private static final String PLAIN_ASCII =
      "AaEeIiOoUu"    // grave
    + "AaEeIiOoUuYy"  // acute
    + "AaEeIiOoUuYy"  // circumflex
    + "AaOoNn"        // tilde
    + "AaEeIiOoUuYy"  // umlaut
    + "Aa"            // ring
    + "Cc"            // cedilla
    + "OoUu"          // double acute
    ;

    private static final String UNICODE =
     "\u00C0\u00E0\u00C8\u00E8\u00CC\u00EC\u00D2\u00F2\u00D9\u00F9"             
    + "\u00C1\u00E1\u00C9\u00E9\u00CD\u00ED\u00D3\u00F3\u00DA\u00FA\u00DD\u00FD" 
    + "\u00C2\u00E2\u00CA\u00EA\u00CE\u00EE\u00D4\u00F4\u00DB\u00FB\u0176\u0177" 
    + "\u00C3\u00E3\u00D5\u00F5\u00D1\u00F1"
    + "\u00C4\u00E4\u00CB\u00EB\u00CF\u00EF\u00D6\u00F6\u00DC\u00FC\u0178\u00FF" 
    + "\u00C5\u00E5"                                                             
    + "\u00C7\u00E7" 
    + "\u0150\u0151\u0170\u0171" 
    ;

    // private constructor, can't be instanciated!
    private AsciiUtils() { }

    // remove accentued from a string and replace with ascii equivalent
    public static String convertNonAscii(String s) {
       if (s == null) return null;
       StringBuilder sb = new StringBuilder();
       int n = s.length();
       for (int i = 0; i < n; i++) {
          char c = s.charAt(i);
          int pos = UNICODE.indexOf(c);
          if (pos > -1){
              sb.append(PLAIN_ASCII.charAt(pos));
          }
          else {
              sb.append(c);
          }
       }
       return sb.toString();
    }

    public static void main(String args[]) {
       String s = 
         "The result : È,É,Ê,Ë,Û,Ù,Ï,Î,À,Â,Ô,è,é,ê,ë,û,ù,ï,î,à,â,ô,ç";
       System.out.println(AsciiUtils.convertNonAscii(s));
       // output : 
       // The result : E,E,E,E,U,U,I,I,A,A,O,e,e,e,e,u,u,i,i,a,a,o,c
    }
}

JDK 1.6 предоставляет класс java.text.Normalizer, который может быть используется для этой задачи.

См. пример здесь

6
ответ дан 24 November 2019 в 00:50
поделиться

Вы можете попробовать использовать unidecode , который доступен как ruby ​​gem и как модуль Perl на cpan . По сути, он работает как огромная таблица поиска, где каждая кодовая точка Unicode относится к символу или строке ascii.

4
ответ дан 24 November 2019 в 00:50
поделиться

Проблема с "преобразованием" произвольного Unicode в ASCII заключается в том, что значение персонажа зависит от культуры. Например, «ß» для немецкоязычного человека следует преобразовать в «ss», в то время как англоговорящий, вероятно, преобразовал бы его в «B».

Добавьте к этому тот факт, что Unicode имеет несколько кодовых точек для одного и того же глифы.

В результате единственный способ сделать это - создать массивную таблицу с каждым символом Unicode и символом ASCII, в который вы хотите его преобразовать. Вы можете использовать ярлык, нормализовав символы с диакритическими знаками до нормализации формы KD, но не все символы нормализуются до ASCII. Кроме того, Unicode не определяет, какие части глифа являются «акцентами».

Вот небольшой отрывок из приложения, которое делает это:

switch (c)
{
    case 'A':
    case '\u00C0':  //  À LATIN CAPITAL LETTER A WITH GRAVE
    case '\u00C1':  //  Á LATIN CAPITAL LETTER A WITH ACUTE
    case '\u00C2':  //  Â LATIN CAPITAL LETTER A WITH CIRCUMFLEX
    // and so on for about 20 lines...
        return "A";
        break;

    case '\u00C6'://  Æ LATIN CAPITAL LIGATURE AE
        return "AE";
        break;

    // And so on for pages...
}
4
ответ дан 24 November 2019 в 00:50
поделиться

Нет простого или общего способа сделать то, что вы хотите, потому что это всего лишь ваше субъективное мнение, что эти буквы выглядят так же, как латинские буквы, в которые вы хотите преобразовать. На самом деле это отдельные буквы со своими собственными именами и звуками, которые внешне выглядят как латинские буквы.

Если вы хотите это преобразование, вы должны создать свою собственную таблицу перевода на основе того, в какие латинские буквы, по вашему мнению, должны быть преобразованы нелатинские буквы.

(Если вы хотите удалить только диакритические знаки, есть некоторые ответы в этой теме: Как удалить диакритические знаки (диакритические знаки) из строки в .NET? Однако вы описываете более общую проблему)

На самом деле это отдельные буквы со своими собственными именами и звуками, которые внешне выглядят как латинские буквы.

Если вы хотите это преобразование, вы должны создать свою собственную таблицу перевода на основе того, в какие латинские буквы, по вашему мнению, должны быть преобразованы нелатинские буквы.

(Если вы хотите удалить только диакритические знаки, есть некоторые ответы в этой теме: Как удалить диакритические знаки (диакритические знаки) из строки в .NET? Однако вы описываете более общую проблему)

На самом деле это отдельные буквы со своими собственными именами и звуками, которые внешне выглядят как латинские буквы.

Если вы хотите это преобразование, вы должны создать свою собственную таблицу перевода на основе того, в какие латинские буквы, по вашему мнению, должны быть преобразованы нелатинские буквы.

(Если вы хотите удалить только диакритические знаки, есть некоторые ответы в этой теме: Как удалить диакритические знаки (диакритические знаки) из строки в .NET? Однако вы описываете более общую проблему)

4
ответ дан 24 November 2019 в 00:50
поделиться

Поскольку кодирование, которое превращает «Семейство» в «tђє Ŧ ค ๓ เ ℓy», является фактически случайным и не следует никакому алгоритму, который может быть объяснен информацией задействованных кодовых точек Unicode, существует нет общего способа решить эту проблему алгоритмически.

Вам нужно будет построить отображение символов Unicode в латинские символы, которые они похожи. Вероятно, вы могли бы сделать это с помощью интеллектуального машинного обучения на реальных глифах, представляющих кодовые точки Unicode. Но я думаю, что для этого потребуется больше усилий, чем при построении карты вручную. Особенно, если у вас есть достаточное количество примеров, из которых вы можете построить свое отображение.

Чтобы уточнить: некоторые из замен действительно могут быть решены с помощью данных Unicode (как показывают другие ответы), но некоторые буквы просто не имеют разумной связи с латинскими символами, на которые они похожи.

Примеры:

  • «ђ» (U + 0452 КИРИЛИЧЕСКАЯ СТРОЧНАЯ БУКВА DJE) больше относится к «d», чем к «h», но используется для обозначения "h".
  • "" (U + 0166 ЛАТИНСКАЯ ЗАГЛАВНАЯ БУКВА T С ИНСУЛЬТОМ) в некоторой степени связано с "T" (как следует из названия), но используется для представления "F".
  • «ค» (U + 0E04 THAI CHARACTER KHO KHWAI) вообще не связано ни с каким латинским символом и в вашем примере используется для обозначения «a»
15
ответ дан 24 November 2019 в 00:50
поделиться
Другие вопросы по тегам:

Похожие вопросы: