Где я могу найти определенный набор правил сопоставления для сравнения сравнений строк?
Мы все знаем, что использование метода 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.