如何使用Python获得“合理”的字符串排序?
我的用户大多是德国人,他们需要从一个长列表中选择元素。我将实现自动完成,但我也希望按照他们期望的顺序向他们展示元素。我向几个用户询问了典型字符串的排序,发现它们基本上是一致的。但是,很难实现这种排序:如何使用Python获得“合理”的字符串排序?,python,sorting,natsort,Python,Sorting,Natsort,我的用户大多是德国人,他们需要从一个长列表中选择元素。我将实现自动完成,但我也希望按照他们期望的顺序向他们展示元素。我向几个用户询问了典型字符串的排序,发现它们基本上是一致的。但是,很难实现这种排序: user_expectation(l) " < @ 1 2 10 10abc A e é E
user_expectation(l) " < @ 1 2 10 10abc A e é E Z
sorted(l) " 1 10 10abc 2 < @ A E Z e é
sorted(l, key=lambda w: w.lower()) " 1 10 10abc 2 < @ A e E Z é
ns.natsorted(l) 1 2 10 10abc " < @ A E Z e é
ns.natsorted(l, alg=ns.I) 1 2 10 10abc " < @ A E Z e é
ns.natsorted(l, alg=ns.LOCALE | ns.LF | ns.G) 1 2 10 10abc " < @ A E e Z é
ns.natsorted(l, alg=ns.LOCALE | ns.LF | ns.G), en 1 2 10 10abc < " @ A E e é Z
ns.natsorted(l, alg=ns.LOCALE | ns.LF | ns.G), de 1 2 10 10abc < " @ A E e é Z
ns.natsorted(l, alg=ns.LF | ns.G), de 1 2 10 10abc " < @ A e E Z é
因此:
首先是特殊字符-顺序并不重要,只要是一致的
接下来是数字。通过匹配前缀对数字进行数字排序,因此['1','10','2']
拉丁字母1?
非重音优先
大写前小写,但这可能并不那么重要
口音/特别的
密码
natsort和IGNORECASE、LOWERCASEFIRST、LOCALE de或en组非常接近。我不喜欢的是特殊字符在数字后面。有办法解决吗?LF似乎没有效果您可以使用键参数将特殊字符替换为在数字之前排序的字符,例如空格
sorted或natsorted随后将按修改后的字符串进行排序,但仍将返回原始字符串
一个简化的例子,只处理特殊字符和数字
进口稀土
def替换_特殊件:
根据需要向正则表达式添加更多字符
返回re.sub'[自natsort版本>=5.1.0起,重音字符应立即处理
下面是一种将特殊字符置于数字之前的方法
import re
import natsort as ns
def special_chars_first(x):
'''Ensure special characters are sorted first.'''
# You can add error handling here if needed.
# If you need '_' to be considered a special character,
# use [0-9A-Za-z] instead of \W.
return re.sub(r'^(\W)', r'0\1', x)
# An alternate, less-hacky solution.
#if re.match(r'\W', x):
# return float('-inf'), x
#else:
# return float('inf'), x
l = ['"', "<", "@", "1", "2", "10", "10abc", "A", "e", "é", "E", "Z"]
print(ns.natsorted(l, key=special_chars_first, alg=ns.G | ns.LF))
输出
['"', '<', '@', '1', '2', '10', '10abc', 'A', 'e', 'é', 'E', 'Z']
这是通过在任何以非单词字符开头的字符串前面加前缀来实现的,该字符定义为除字母、数字或带有“0”的“uu”之外的任何字符,这将保证它们在任何其他数字之前结束,并且根据now natsort works,数字始终是第一位的。是否所有特殊字符都应该在数字之后,或者如果该字符串只是特殊字符字符?例如,@和@hello都应该在1之前吗?所有特殊字符都应该在数字之前。所以,@和@hello都应该在1之前。你能更新用户在问题中的预期顺序,以便复制/粘贴显示正确的结果吗?根据你对我的评论的回复,用户应该是1、2、10,而不是1、10、2、10在问题的两个示例中,它们仍然显示了后者而不是前者。@SethMMorton感谢您,规范化数据的功能应该内置于natsort中。我为此提出了一个问题:当列表项以00开头时,您的特殊字符第一个解决方案将中断。我不同意。我只是在给定列表中添加了00@并获得了输出['','奇怪…但是,好吧,只需将00添加到列表中即可。@poke如果添加几个前导零会把事情搞砸,这将不是一个非常健壮的自然排序算法:
['"', '<', '@', '1', '2', '10', '10abc', 'A', 'e', 'é', 'E', 'Z']