Где я могу найти определенный набор правил сопоставления для сравнения сравнений строк?

Мы все знаем, что использование метода String equals() для сравнения равенства потерпит неудачу. Вместо этого следует использовать Collator, например:

// we need to detect User Interface locale somehow
Locale uiLocale = Locale.forLanguageTag("da-DK");
// Setting up collator object
Collator collator = Collator.getInstance(uiLocale);
collator.setStrength(Collator.SECONDARY);
collator.setDecomposition(Collator.CANONICAL_DECOMPOSITION);
// strings for equality testing
String test1 = "USA lover Grækenland støtte";
String test2 = "USA lover graekenland støtte";
boolean result = collator.equals(test1, test2);

Теперь этот код работает, то есть результат true , если uiLocale не установлен на датский язык. В таком случае это приведет к ложному. Я, конечно, понимаю , почему это произошло: это только потому, что метод equals реализован следующим образом:

return compare(s1, s2) == Collator.Equal;

Этот метод вызывает тот, который используется для сортировки и проверяет, совпадают ли строки. Это не так, потому что для датских специфических правил сортировки требуется сортировка æ после (если я правильно понял результат метода сравнения) ae. Тем не менее, эти строки действительно одинаковы, с этой силой как разности случаев, так и такие символы совместимости (то, что их называют) следует рассматривать как равные.

Чтобы исправить это, можно использовать RuleBasedCollator с определенным набором правил, который будет работать для случая равенства.
Наконец, возникает вопрос: знает ли кто-нибудь, где я могу получить такие конкретные правила (не только для датчан, но и для других языков), чтобы символы совместимости, лигатуры и т.д. Считались равными (CLDR , похоже, не содержит таких, или я не смог его найти)?

Или, может быть, я хочу сделать что-то глупое здесь, и я должен использовать просто UCA для сравнения равенства (любой пример кода, пожалуйста)?

Ответы

Ответ 1

Я не могу найти никакого существующего Collator для датчан; встроенный для датского языка должен быть правильным. Я не уверен, что ваше предположение, что ae должно быть отсортировано с помощью æ, выполняется, в частности, из-за некоторых иностранных слов (например "aerofobi" ) на датском языке (я не датский оратор, хотя я говорю шведский).

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

String str = "USA lover graekenland støtte";
String sortStr = str.replace("ae", "æ");

Другой, возможно, лучший вариант - тот, который вы указали; используя RuleBasedCollator. Используя пример из javadocs, это довольно тривиально:

String danish = "< a, A < b, B < c, C < d, D < e, E < f, F < g, G < h, H < i, I" +
                "< j, J < k, K < l, L < m, M < n, N < o, O < p, P < q, Q < r, R" +
                "< s, S < t, T < u, U < v, V < w, W < x, X < y, Y < z, Z" +
                "< \u00E6 = ae," +       // Latin letter ae
                "  \u00C6 = AE " +       // Latin letter AE
                "< \u00F8, \u00D8" +     // Latin letter o & O with stroke
                "< \u00E5 = a\u030A," +  // Latin letter a with ring above
                "  \u00C5 = A\u030A;" +  // Latin letter A with ring above
                "  aa, AA";
RuleBasedCollator danishCollator = new RuleBasedCollator(danish);

Что вы можете использовать:

String test1 = "USA lover Grækenland støtte";
String test2 = "USA lover Graekenland støtte";         // note capital 'G'
boolean result = danishCollator.equals(test1, test2);  // true

Если вы считаете, что по умолчанию не установлен коллатор, вы можете сообщить об ошибке. (Ранее были похожие ошибки).

Обновление: Я проверил это с помощью печатной энциклопедии на датском языке. Есть действительно слово, которое начинается с "ae" (прежде всего слова с иностранных языков, например "аэробика" ), которые не сортируются с (и, следовательно, не равны) слову, начинающимся с "æ". Поэтому, хотя я понимаю, почему вы хотели бы относиться к ним как к равным во многих обстоятельствах, они не являются строго такими.

Ответ 2

Одним из способов получения правил для конкретной локали является использование функции getRules. Однако в Android эта функция возвращает пустую строку.

    RuleBasedCollator collTemp = (RuleBasedCollator) Collator
            .getInstance(Locale.US);
    String usRules = collTemp.getRules();


    //Save rules in a file
    String rulesPath = "C:\\projects\\droid\\rules.txt";
    BufferedWriter out = new BufferedWriter
            (new OutputStreamWriter(new FileOutputStream(rulesPath),"UTF-16"));
    out.write(usRules);
    out.close();

Эти правила являются теми же, что используются функцией сравнения.

if (collTemp.compare(target, str) < 0)

Примечание. Я попытался подключить правила из строки приложения JDK для настольных приложений в конструктор RuleBasedCollator для Android, но я получаю U_INVALID_FORMAT_ERROR (только для Android). Поэтому я все еще пытаюсь понять, как получить правила США в Android.