Python中的正则表达式问题

时间:2019-03-20 12:36:47

标签: python regex natural-sort

我在python中有一个函数,用于为Natural-Sort / Human算法返回给定键的元组。

请参见fake _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

因为小字符优先处理...

期望:

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)

2 个答案:

答案 0 :(得分: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-containing-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似乎不是解决问题的合适标签和/或方法。 希望对您有帮助

答案 1 :(得分: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的密钥生成器:

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

请注意,您不一定需要使用语言环境...您只需要适当地规范unicode,natsort会自动在后台执行。在您的情况下,您似乎想同时将大写字母和小写字母与小写字母分组在一起,因此您可以改用它

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

我之所以建议这样做,是因为尝试处理语言环境是一场噩梦,如果不需要,那么您的境况会好很多。