Проблема с регулярным выражением в Python

1

У меня есть функция в Python, которая возвращает кортеж данного ключа для алгоритма Natural-Sort/Human.

Смотрите поддельные _human_key.

Но мне нужно это изменить, чтобы заменить немецкие умлауты их стандартными алфавитными символами.

Короче говоря, я хочу избавиться от Ä, Ö, Ü, ß для сортировки.

Также дело не стоит рассматривать. Маленькое d должно иметь тот же приоритет, что и заглавное D...

Для умлаутов я использую функцию замены, которая кажется довольно неловким способом сделать это...: -/У меня нет лучшей идеи... Есть предложения?

Также я не могу переписать это, чтобы избавиться от чувствительности к регистру...

Пока что у меня есть:

def _human_key(key):
    key = key.replace("Ä", "A").replace("Ö", "O").replace("Ü", "U")\
          .replace("ä", "a").replace("ö", "o").replace("ü", "u")\
          .replace("ß", "s")
    parts = re.split(r'(\d*\.\d+|\d+)', key)   
    return tuple((e.swapcase() if i % 2 == 0 else float(e))
            for i, e in enumerate(parts))
    return parts

Примеры: у меня есть значения

 Zabel
 Schneider
 anabel
 Arachno
 Öztürk
 de 'Hahn

который я хочу отсортировать; в настоящее время это ставит:

anabel
de 'Hahn
Arachno
Öztürk
Schneider
Zabel

потому что маленькие символы обрабатываются с приоритетом...

Expectation:

anabel
Arachno
de 'Hahn   ( <-- because "d" comes after "a")
Öztürk
Schneider

Я чувствую, что замена не является правильным способом решения проблемы с умлаутами, но не могу найти лучшего решения.

Обновление/Справочная информация:

Я звоню это извне, из класса "QSortFilterProxyModel", мне это нужно для сортировки строк по их нажатым столбцам. У меня есть QTreeView, который отображает набор результатов из базы данных, а один столбец содержит немецкие фамилии, что фон.

class HumanProxyModel(QtCore.QSortFilterProxyModel):
    def lessThan(self, source_left, source_right):
        data_left = source_left.data()
        data_right = source_right.data()
        if type(data_left) == type(data_right) == str:            
            return _human_key(data_left) < _human_key(data_right)            
        return super(HumanProxyModel, self).lessThan(source_left, source_right)
  • 0
    Почему бы не пойти с чем-то вроде stackoverflow.com/a/25057291/3820185
  • 0
    Почему вы хотите заменить символы Юникода? В конце концов, они персонажи.
Показать ещё 4 комментария
Теги:
natural-sort

2 ответа

0
Лучший ответ

Если вы не возражаете против использования сторонних модулей, вы можете использовать natsort (полное раскрытие, я автор). Для данных, которые вы предоставляете, он возвращает то, что вы хотите из коробки.

>>> from natsort import natsorted, ns
>>> data = ['Zabel', 'Schneider', 'anabel', 'Arachno', 'Öztürk', 'de Hahn']
>>> natsorted(data, alg=ns.LOCALE)  # ns.LOCALE turns on locale-aware handling
['anabel', 'Arachno', 'de Hahn', 'Öztürk', 'Schneider', 'Zabel']
>>> from natsort import humansorted
>>> humansorted(data)  # shortcut for using LOCALE
['anabel', 'Arachno', 'de Hahn', 'Öztürk', 'Schneider', 'Zabel']

Если вам нужен ключ сортировки, вы можете использовать natsort ключей natsort:

>>> from natsort import natsort_keygen, ns
>>> humansort_key = natsort_keygen(alg=ns.LOCALE)
>>> humansort_key(this) < humansort_key(that)

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

>>> natsorted(data, alg=ns.GROUPLETTERS | ns.LOWERCASEFIRST)  # or ns.G | ns.LF
['anabel', 'Arachno', 'de Hahn', 'Öztürk', 'Schneider', 'Zabel']

Я предлагаю это, потому что пытаться разобраться с локалью - это кошмар, и если это не нужно, тогда вам гораздо лучше.

  • 0
    спасибо, похоже, все работает так, как я хочу: из natsort import natsort_keygen, ns peopleort_key = natsort_keygen (alg = ns.LOCALE), класс HumanProxyModel (QtCore.QSortFilterProxyModel): def lessThan (self, source_left, source_right): data_ = source_left.data () data_right = source_right.data () if type (data_left) == type (data_right) == str: return peopleort_key (data_left) <peopleort_key (data_right) вернуть super (HumanProxyModel, self) .lessThan (source_left, source_right)
1

это помогает?

import locale
locale.setlocale(locale.LC_ALL, "")

lst = ['Zabel', 'Schneider', 'anabel', 'Arachno', 'Öztürk', 'de Hahn']

print(sorted(lst, key=locale.strxfrm))

дал мне:

['anabel', 'Arachno', 'de Hahn', 'Öztürk', 'Schneider', 'Zabel']

Чтобы идти дальше, я был на: http://code.activestate.com/recipes/576507-sort-strings-conisting-german-umlauts-in-correct-/

ОБНОВИТЬ

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

import locale
locale.setlocale(locale.LC_ALL, "")

lst = ['Zabel', 'Schneider', 'anabel', 'Arachno', 'Öztürk', 'de Hahn']

def _human_key(your_list):
    your_list.sort(key=locale.strxfrm)
    res = []
    for item in your_list:
        word = item.replace("Ä", "A").replace("Ö", "O").replace("Ü", "U")\
              .replace("ä", "a").replace("ö", "o").replace("ü", "u")\
              .replace("ß", "s")
        res.append(word)
    return res

print(_human_key(lst))

дал мне:

['anabel', 'Arachno', 'de Hahn', 'Ozturk', 'Schneider', 'Zabel']

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

  • 0
    выглядит хорошо, но как это сделать в функцию _human_key ()? Понятия не имею... :-/
  • 1
    @ ProfP30 Вам больше не нужна функция _human_key . Вы можете использовать lst.sort(key=locale.strxfrm) ... @Nqsir Когда я использую это решение, «Öztürk» предшествует «de Hahn»
Показать ещё 6 комментариев

Ещё вопросы

Сообщество Overcoder
Наверх
Меню