Сортировать список кортежей с учетом локали (шведский порядок) - PullRequest
7 голосов
/ 03 марта 2012

Очевидно, что PostgreSQL 8.4 и Ubuntu 10.04 не могут обработать обновленный способ сортировки W и V для шведского алфавита. То есть он все еще упорядочивает их как одну и ту же букву (старое определение для шведского упорядочения):

  • Wa
  • Vb
  • Wc
  • Vd

должно быть (новое определение для шведского заказа):

  • Vb
  • Vd
  • Wa
  • Wc

Мне нужно правильно заказать это для сайта Python / Django, который я создаю. Я пробовал различные способы, чтобы просто заказать список кортежей, созданный из Django QuerySet, используя * values_list *. Но так как это также шведский, буквы ä и ö должны быть правильно упорядочены. Теперь у меня есть либо один, либо другой путь, а не оба ..

list_of_tuples = [(u'Wa', 1), (u'Vb',2), (u'Wc',3), (u'Vd',4), (u'Öa',5), (u'äa',6), (u'Åa',7)]

print '########## Ordering One ##############'
ordered_list_one = sorted(list_of_tuples, key=lambda t: tuple(t[0].lower()))
for item in ordered_list_one:
    print item[0]

print '########## Ordering Two ##############'
locale.setlocale(locale.LC_ALL, "sv_SE.utf8")
list_of_names = [u'Wa', u'Vb', u'Wc', u'Vd', u'Öa', u'äa', u'Åa']
ordered_list_two = sorted(list_of_names, cmp=locale.strcoll)
for item in ordered_list_two:
    print item

Примеры дают:

########## Ordering One ##############
Vb
Vd
Wa
Wc
äa
Åa
Öa
########## Ordering Two ##############
Wa
Vb
Wc
Vd
Åa
äa
Öa

Теперь, то, что я хочу, это их комбинация, чтобы и V / W, и порядок упорядочения å, ä, ö были правильными. Чтобы быть более точным. Я хочу, чтобы Ordering One уважал язык. Затем, используя второй элемент (идентификатор объекта) в каждом кортеже, я мог получить правильный объект в Django.

Я начинаю сомневаться, что это будет возможно? Возможно ли будет обновить PostgreSQL до более новой версии, которая лучше обрабатывает параметры сортировки, а затем использовать сырой SQL в Django?

Ответы [ 2 ]

8 голосов
/ 04 марта 2012

При запуске LC_ALL=sv_SE.UTF-8 sort в вашем примере на Ubuntu-10.04 он выходит с Wa до Vb («старый путь»), поэтому Ubuntu, похоже, не согласен с «новым способом». Поскольку для этого PostgreSQL использует операционную систему, он будет вести себя так же, как и ОС с той же lc_collate.

На самом деле в Debian Glibc есть патч, связанный с этой конкретной проблемой сортировки: http://sourceware.org/bugzilla/show_bug.cgi?id=9724 Но это было против и не принято. Если вам нужно такое поведение только в системе, которую вы администрируете, вы все равно можете применить изменение патча к / usr / share / i18n / locales / sv_SE и перестроить локаль se_SV, запустив locale-gen sv_SE.UTF-8. Или, что еще лучше, создайте свой собственный альтернативный язык, полученный из него, чтобы избежать путаницы с оригиналом.

0 голосов
/ 08 марта 2016

Это решение сложное, потому что key = locale.strxfrm работает нормально с отдельными списками и словарями, но не со списками списков или списки кортежей.

Изменения от Py2 -> Py3: используйте locale.setlocale (locale.LC_ALL, '') и ключ = 'locale.strxfrm' (вместо 'cmp = locale.strcoll').

list_of_tuples = [('Wa', 1), ('Vb',2), ('Wc',3), ('Vd',4), ('Öa',5), ('äa',6), ('Åa',7)]

def locTupSorter(uLot):
    "Locale-wise list of tuples sorter - works with most European languages"
    import locale
    locale.setlocale(locale.LC_ALL, '') # get current locale

    dicTups = dict(uLot)          # list of tups to unsorted dictionary
    ssList = sorted(dicTups, key=locale.strxfrm)
    sLot = []
    for i in range(len(ssList)):  # builds a sorted list of tups 
        tfLot = ()
        elem = ssList[i]          # creates tuples for list
        tfLot = (elem, dicTups[elem])
        sLot.append(tfLot)        # creates sorted list of tuples
    return(sLot)


print("list_of_tuples=\n", list_of_tuples)
sortedLot = locTupSorter(list_of_tuples)
print("sorted list of tuples=\n",sortedLot)
...