У меня есть функция в 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)
Если вы не возражаете против использования сторонних модулей, вы можете использовать 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']
Я предлагаю это, потому что пытаться разобраться с локалью - это кошмар, и если это не нужно, тогда вам гораздо лучше.
это помогает?
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 не кажется подходящим тэгом и/или подходом к вашей проблеме, если вы не можете реализовать предыдущий код в своем методе. Надеюсь, это помогло
_human_key
. Вы можете использовать lst.sort(key=locale.strxfrm)
... @Nqsir Когда я использую это решение, «Öztürk» предшествует «de Hahn»