我得到了这种奇怪的行为:
>>> locale.setlocale(locale.LC_ALL, 'de_DE.utf-8')
'de_DE.utf-8'
>>> sorted([u'<NULL', u'NULL>', u'<NULL>', u'NULL', u'a'], cmp=locale.strcoll)
[u'a', u'<NULL', u'<NULL>', u'NULL', u'NULL>']
>>> sorted(['<NULL', 'NULL>', '<NULL>', 'NULL', 'a'], cmp=locale.strcoll)
['a', 'NULL', 'NULL>', '<NULL', '<NULL>']
虽然可以在“a”之后对“ 有办法解决这个问题吗? 更新:PyICU 给出的结果与上述两者不同。>>> import PyICU
collator = PyICU.Collator.createInstance(PyICU.Locale('de_DE.UTF-8'))
>>> sorted([u'<NULL', u'NULL>', u'<NULL>', u'NULL', u'a'], cmp=collator.compare)
[u'<NULL', u'<NULL>', u'a', u'NULL', u'NULL>']
最佳答案
解决方法是始终使用 unicode(或字节字符串)作为键:
import locale
from functools import cmp_to_key
@cmp_to_key
def strcoll(a, b):
if isinstance(a, str):
a = a.decode('utf-8')
if isinstance(b, str):
b = b.decode('utf-8')
return locale.strcoll(a, b)
然后以下应该给出相同的输出:
sorted([u'<NULL', u'NULL>', u'<NULL>', u'NULL', u'a'], key=strcoll)
sorted(['<NULL', 'NULL>', '<NULL>', 'NULL', 'a'], key=strcoll)
我会使用key
而不是cmp
因为它更便携。
一个更简单的方法是简单地将所有字符串显式保留为 unicodes/bytes:
def to_unicode(s):
return s.decode('utf-8') if isinstance(s, str) else s
the_list = [...]
the_list = [to_unicode(elem) for elem in the_list]
这种方法的优点是可以在 str
之间进行一次转换。和unicode
,而另一种方法则在每次比较时进行转换(甚至使用 key
和 cmp_to_key
)。
关于Python 排序顺序 unicode/ansi 不同,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15768649/