Сортировка строк с несколькими локалями в Java - PullRequest
6 голосов
/ 17 ноября 2010

Я пытаюсь отсортировать список объектов по строковому полю "страна".Каждая страна на своем родном языке

  • Аргентина
  • Австралия
  • Österreich
  • Ελλάδα
  • България ...

То, что я хочу сделать, это получить, например, «България» после стран «А *», поскольку буква «Б» соответствует латинскому значку «В».Я пытаюсь использовать Collater по умолчанию, но нелатинские имена все еще остаются последними в списке.

Вот мой код:

private static final Comparator<DomainTO> DOMAIN_COUNTRY_COMPARATOR =
    new Comparator<DomainTO>() {
    @Override
    public int compare(DomainTO t, DomainTO t1) {
        Collator defaultCollator = Collator.getInstance();
        return defaultCollator.compare(t.getCountry(), t1.getCountry());
    }
};

Ответы [ 2 ]

34 голосов
/ 07 декабря 2014

Как сортировать слова из разных языков? Есть много алфавитов (английский, русский, немецкий и т. Д.). Каждый заказал список писем. Легко сортировать слова из одного алфавита. Но возможно ли объединить все эти алфавиты в один?
Я думаю, что это невозможно сделать так, чтобы все могли это принять. В качестве примера возьмем английский и русский алфавиты. Русские буквы могут быть преобразованы в английские буквы (по крайней мере, большинство из них), но после этого преобразования они изменят порядок. Это было бы предпочтение одного алфавита над другим. Почему бы не переводить английские буквы на русский?
Другая проблема заключается в том, что есть специальные письма. В немецком есть Ö между O и P, а в польском есть Ó в этом месте. Итак, мы имеем следующие отношения:

O < Ö < P  
O < Ó < P

Но какова связь между Ö и Ó? Если была страна Эстеррайх, должна ли она быть до или после Эстеррайха? Поэтому невозможно определить универсальные правила сортировки слов из разных языков.

Все, что мы можем сделать, это привести все алфавиты к выбранному. И это то, что ОП пытается сделать.
Выбранным является латинский алфавит, и другие алфавиты должны быть приведены к этому. Проблема в том, что этот кастинг часто неоднозначен. Легко мы можем читать только большинство русских или греческих букв.
Гораздо большая проблема с арабским или азиатским языками. И мы должны помнить, что при переходе от одного алфавита к другому мы часто что-то теряем.

Так, как мы можем сделать такую ​​сортировку?

  1. Первое предложение - вручную указать латинское название для каждой страны. Таким образом, у нас был бы список, содержащий пары, такие как
    • Россия Россия
    • Elλλάδα Эллада
      Тогда мы могли бы сортировать по латинскому имени и отображаемым именам.
  2. Второй подход - запуск кода, подобного следующему:

Код:

char [] russian = "АаБбВвГгДдЕеЁёЖжЗзИиЙйКкЛлМмНнОоПпРрСсТтУуФфХхЦцЧчШшЩщ".toCharArray();  
char [] russian_to = "AaBbWwGgDdEeEeZzZzIiJjKkLlMmNnOoPpRrSsTtUuFfHhCcCcSsss".toCharArray();  
for (int i = 0; i < russian.length; i++) {
    input = input.replace(russian[i], russian_to[i]);
}

Таким образом, мы конвертировали все буквы русского алфавита. Теперь мы должны добавить аналогичный код для других алфавитов. И русский был самым простым.
Но предположим, что нам это удалось, и нам удалось провести такую ​​сортировку слов со всех языков мира.
Но каковы последствия такой сортировки? Прежде чем ответить на этот вопрос, давайте спросим, ​​каковы были намерения сделать это. ОП не назвал причины, по которым он занимается такой сортировкой. Но мы можем вывести это:

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

Итак, давайте ответим на вопрос: облегчает ли эта сортировка поиск конкретной страны человеку, который знает только свой родной язык?

  1. Если кто-то из Австрии, он предполагает, что Österreich будет после всех стран, начинающихся с O. Но после нормализации Остеррайх станет Остеррайхом и окажется где-то между Онтарио и Оттавой. (Я знаю, что Онтарио и Оттава не являются странами. Это только пример).
  2. Если кто-то из Японии и не знает латинского алфавита, тогда эта сортировка была бы для него бесполезной. Ему придется просмотреть весь список, пока он не найдет свою страну.
  3. Предположим, что есть страна Волгоград (Волгоград) и есть гражданин этой страны, который знает только русский алфавит. В русском алфавите В - третья буква, поэтому этот человек будет искать в начале списка (где-то между Бельгией и Данией), когда Волгоград будет в конце списка (рядом с Венесуэлой). поэтому в этом случае сортировка будет не только бесполезной, но и вводящей в заблуждение.
  4. Если кто-то знает латинский алфавит и ищет свою страну, это не может быть легко. Когда все страны названы на английском языке, а я смотрю «Польша», я всегда знаю, стоит ли мне идти вверх или вниз по списку. Если я вижу «Японию», я знаю, чтобы идти вниз по списку. Когда я вижу «Россию», я знаю, что нужно идти вверх.
    Но если бы мы сделали сортировку по всем этим именамВ таком случае может возникнуть проблема.Если бы я увидел ايران, то я бы не смог решить, идти вверх или вниз по списку.Так что в этом примере сортировка не помогает.Хуже сценарий, когда я встречаю Волгоград в списке.Я не знаю русского алфавита, и я предполагаю, что я нахожусь рядом с буквой «В», хотя на самом деле я близок к концу списка.Тогда я бы выбрал неправильное направление.

Резюме:

Сортировка названий стран, написанных на разных языках, трудно определить и реализовать.И когда оно будет реализовано, оно будет либо бесполезным, либо вредным.

2 голосов
/ 17 ноября 2010

Возможно, вы можете сравнить нормализованные строки. Примерно так:

private static final Comparator<DomainTO> DOMAIN_COUNTRY_COMPARATOR =
    new Comparator<DomainTO>() {

        private String normalize(final String input) {
            return Normalizer
                .normalize(input, Normalizer.Form.NFD)
                .replaceAll("[^\\p{ASCII}]", "");
        }

        @Override
        public int compare(final DomainTO t, final DomainTO t1) {
            return normalize(t.getCountry()).compareTo(
                normalize(t1.getCountry()));
        }
    };

См. Связанный вопрос о нормализации: Преобразование строки Java в ascii (этот вопрос связан с несколькими похожими вопросами)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...