Удаление диакритических знаков из символов Юникода
Я рассматриваю алгоритм, который может сопоставлять символы с диакритическими знаками (тильда, окружность, каретка, умлаут, карон) и их "простым" символом.
Например:
ń ǹ ň ñ ṅ ņ ṇ ṋ ṉ ̈ ɲ ƞ ᶇ ɳ ȵ --> n á --> a ä --> a ấ --> a ṏ --> o
И др.
Я хочу сделать это на Java, хотя подозреваю, что это должно быть что-то на языке Unicode и должно быть достаточно легко выполнимо на любом языке.
Цель: упростить поиск слов с диакритическими знаками. Например, если у меня есть база данных теннисистов, и в ней введен Björn_Borg, я также сохраню Bjorn_Borg, чтобы я мог найти его, если кто-то введет Bjorn, а не Björn.
но это не удастся, например, в Białystok, потому что ł символ не является диакритическим.
Если вы хотите иметь полноценный упрощитель строк, вам потребуется второй раунд очистки для еще нескольких специальных символов, которые не являются диакритическими знаками. В эту карту я включил наиболее распространенные специальные символы, которые появляются в именах наших клиентов. Это не полный список, но он даст вам представление о том, как его расширить. ImmutableMap - это всего лишь простой класс из Google-коллекций.
publicstatic String simplifiedString(String orig) { Stringstr= orig; if (str == null) { returnnull; } str = stripDiacritics(str); str = stripNonDiacritics(str); if (str.length() == 0) { // Ugly special case to work around non-existing empty strings // in Oracle. Store original crapstring as simplified. // It would return an empty string if Oracle could store it. return orig; } return str.toLowerCase(); }
/* Special regular expression character ranges relevant for simplification: - InCombiningDiacriticalMarks: diacritic marks used in many languages - IsLm: Letter, Modifier (see http://www.fileformat.info/info/unicode/category/Lm/list.htm) - IsSk: Symbol, Modifier (see http://www.fileformat.info/info/unicode/category/Sk/list.htm) - U+0591 to U+05C7: Range for Hebrew diacritics (niqqud) (see official Unicode chart: https://www.unicode.org/charts/PDF/U0590.pdf) */ publicstaticfinalPatternDIACRITICS_AND_FRIENDS= Pattern.compile( "[\\p{InCombiningDiacriticalMarks}\\p{IsLm}\\p{IsSk}\\u0591-\\u05C7]+" );
Основной пакет java.text был разработан для решения этого варианта использования (сопоставление строк без учета диакритических знаков, регистра и т.д.).
Настройте Collator для сортировки по PRIMARY различиям в символах. После этого создайте CollationKey для каждой строки. Если весь ваш код написан на Java, вы можете использовать CollationKey напрямую. Если вам нужно сохранить ключи в базе данных или другом виде индекса, вы можете преобразовать его в массив байтов.
Эти классы используют данные о сложении регистра в стандарте Юникода, чтобы определить, какие символы эквивалентны, и поддерживают различные стратегии декомпозиции.
Обратите внимание, что средства сортировки зависят от локали. Это связано с тем, что "алфавитный порядок" отличается в разных локалях (и даже с течением времени, как это было в случае с испанским). Класс Collator избавляет вас от необходимости отслеживать все эти правила и поддерживать их в актуальном состоянии.
Но еще предстоит проделать некоторую работу, поскольку Java создает странные вещи с неконвертируемыми символами Юникода (она не игнорирует их и не создает исключение). Но я думаю, вы могли бы использовать это в качестве отправной точки.