import locale
locale.setlocale(locale.LC_COLLATE,'hu_HU.ISO8859-2')
print(sorted(['c', 'á', 'b', 'z', 'é', 'a', 'd', 'e', 'f', 'Ő', 'Ű', 'ő', 'ű'], key=locale.strxfrm))
预期:['a', 'á', 'b', 'c', 'd', 'e', 'é', 'f', 'Ő', 'ő', 'Ű', 'ű ', 'z']
实际:['a', 'á', 'b', 'c', 'd', 'e', 'é', 'f', 'z', 'Ő', 'ő', 'Ű ', 'ű']
请注意,“z”应该是最后一个字母。
我知道我的代码“有效”,因为它确实将“á”和“é”放在正确的位置(并且“常规”排序将它们放在“z”之后),因此我的错误位于语言环境定义中。
我有MacOS Venture 13.6.4,python 3.11.7
如何“更新”区域设置定义?是Python中的东西还是使用系统区域设置?
注意:我尝试安装PyICU和zope.ucol,但在安装过程中都失败了,所以不要告诉我使用它们。
语言敏感排序在 Python 中是一个复杂的问题:
共有三种方法:
import icu
collator = icu.Collator.createInstance(icu.Locale('hu_HU'))
data = ['c', 'á', 'b', 'z', 'é', 'a', 'd', 'e', 'f', 'Ő', 'Ű', 'ő', 'ű']
print(sorted(data, key=collator.getSortKey))
# ['a', 'á', 'b', 'c', 'd', 'e', 'é', 'f', 'ő', 'Ő', 'ű', 'Ű', 'z']
但是OP更愿意避开这个解决方案。
基本代码是:
import locale
locale.setlocale(locale.LC_COLLATE,'hu_HU.UTF-8')
data = ['c', 'á', 'b', 'z', 'é', 'a', 'd', 'e', 'f', 'Ő', 'Ű', 'ő', 'ű']
print(sorted(data, key=locale.strxfrm))
结果各不相同。 macOS 不支持匈牙利语排序规则。不使用 glibc 的 Linux 发行版将不支持匈牙利排序规则。我没有将 Windows 包含在下表中,但它可以正常工作。
Alpine: ['a', 'b', 'c', 'd', 'e', 'f', 'z', 'á', 'é', 'Ő', 'ő', 'Ű', 'ű']
Freebsd: ['a', 'á', 'b', 'c', 'd', 'e', 'é', 'f', 'ő', 'Ő', 'ű', 'Ű', 'z']
macOS: 'a', 'b', 'c', 'd', 'e', 'f', 'z', 'á', 'é', 'Ő', 'ő', 'Ű', 'ű']
Ubuntu: ['a', 'á', 'b', 'c', 'd', 'e', 'é', 'f', 'ő', 'Ő', 'ű', 'Ű', 'z']
import unicodedata as ud
import regex
data = ['c', 'á', 'b', 'z', 'é', 'a', 'd', 'e', 'f', 'Ő', 'Ű', 'ő', 'ű']
# accent and case insensitive
def ai_si(x):
xn = ud.normalize("NFD", x.casefold())
xn = regex.sub(r'\p{Mn}', '', xn)
return (xn, x.swapcase())
print(sorted(data, key=ai_si))
ai_si()
返回一个元组 (xn, x.swapcase())
。如果仅返回 xn
,大小写和变音符号将被完全忽略,这意味着它们在最终排序中的位置是相对于它们在列表中的位置的。 IE。 á
、Á
、a
和A
相对于彼此没有任何固定顺序,它将由要排序的原始列表中的位置确定。
我们可以使用
x
或 x.swapcase()
作为元组的第二个元素。 x
将创建一个排序顺序,其中大写字符通常(但并非总是)排在小写字符之前。而x.swapcase()
则颠倒了事例之间的相对顺序。还有其他方法可以构造元组的第二个元素。
ai_si()
允许对变音符号和大小写进行二次区分。