Где я могу найти конкретный набор правил сопоставления для сравнения равенств строк? - PullRequest
15 голосов
/ 05 декабря 2011

Все мы знаем, что использование метода 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 chart , по-видимому, не содержит таковых, или я не смог его найти)?

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

Ответы [ 2 ]

3 голосов
/ 24 января 2012

Я не могу найти какой-либо существующий 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' (в основном это слова из иностранных языков; например, "аэробика"), которые не отсортированы с (и, следовательно, не равны) слову, начинающемуся с 'æ'.Поэтому, хотя я понимаю, почему вы хотели бы относиться к ним как к равным во многих обстоятельствах, они не совсем такие.

0 голосов
/ 16 июля 2015

Один из способов получить правила для конкретной локали - использовать функцию 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 для настольных ПК в конструктор Android RuleBasedCollator, но получаю U_INVALID_FORMAT_ERROR (только в Android). Поэтому я все еще пытаюсь понять, как получить правила США в Android.

...