在Python中按(XX-YY)格式排序数字集合

0 投票
4 回答
1134 浏览
提问于 2025-04-18 08:37

我有一个Python列表,里面的值都是这种格式:

CCXX-YY,其中CC是两个字母,所有的值都是一样的,X是一个数字,YY也是数字。

比如:

KA13-1 KA13-2 KA14-2 KA14-1 KA11-12 KA13-11

变成

KA11-12 KA13-1 KA13-2 KA13-11 KA14-1 KA14-2

而不是

KA11-12 KA13-1 KA13-11 KA13-2 KA14-1 KA14-2

我尝试过的办法:

natsort(遇到的问题是把-当成了负号)

后来补充:如果使用参数alg=ns.UNSIGNED,natsort可以正常工作,下面有说明。

naturalsort(在Python 3中不太好用?)

用关键字排序(我知道这样可以做到,但我对Python还不太熟悉,搞不定)

我现在正在尝试的办法:

去掉除了数字以外的所有多余字段,试着根据数字排序(这个有点问题,因为KA12-10会排在KA14-1后面,因为1210比141大)

我不能轻易地把值改成不带连字符的格式,因为我从网站请求数据时需要保持原来的格式,以便查询单个项目。

我相信有经验的人能帮我解决内置排序的问题。

谢谢。

4 个回答

1

更新的回答

natsort 版本 4.0.0 开始,这个功能可以直接使用,不需要特别的选项。

>>> from natsort import natsorted
>>> natsorted('KA11-12 KA13-1 KA13-11 KA13-2 KA14-1 KA14-2'.split())
['KA11-12', 'KA13-1', 'KA13-2', 'KA13-11', 'KA14-1', 'KA14-2']

旧的回答 针对 natsort 版本小于 4.0.0

你提到过因为负号的问题,natsort 对你来说不管用。这是因为默认情况下,负号 '-' 被当作后面数字的一部分来处理,但你可以通过使用 "UNSIGNED" 这个选项来关闭这个功能。

>>> from natsort import natsorted, ns
>>> natsorted('KA11-12 KA13-1 KA13-11 KA13-2 KA14-1 KA14-2'.split(), alg=ns.UNSIGNED)
['KA11-12', 'KA13-1', 'KA13-2', 'KA13-11', 'KA14-1', 'KA14-2']

使用 versorted 也可以解决这个问题。

>>> from natsort import versorted
>>> versorted('KA11-12 KA13-1 KA13-11 KA13-2 KA14-1 KA14-2'.split())
['KA11-12', 'KA13-1', 'KA13-2', 'KA13-11', 'KA14-1', 'KA14-2']

我得坦白一下,我是 natsort 的作者。

1

如果你只想考虑整数部分来进行排序:

l = ['KB13-1', 'KA13-2', 'KC11-11', 'KA14-1', 'KA11-12']
sorted(l, key=lambda i: i[2:])

输出结果

['KC11-11', 'KA11-12', 'KB13-1', 'KA13-2', 'KA14-1']

如果前两个字符永远不变,那么你可以直接使用普通的 sortsorted 函数。

x = ['KA13-1', 'KA13-2', 'KA11-11', 'KA14-1', 'KA11-12']
sorted(x)

输出结果

['KA11-11', 'KA11-12', 'KA13-1', 'KA13-2', 'KA14-1']
3

你想要的排序结果其实就是字典顺序排序。只需要使用 sorted 或者 list.sort,不需要任何特别的规则或比较方式。

2

我觉得真正的问题是,你希望像 KA13-12 这样的东西放在哪里。如果你希望它排在 KA13-2 后面,那么你可能需要类似下面的东西:

>>> seq = "KA13-1 KA13-2 KA14-2 KA14-1 KA11-12 KA13-12".split()
>>> seq.sort(key=lambda x: tuple(map(int, x[2:].split("-"))))
>>> seq
['KA11-12', 'KA13-1', 'KA13-2', 'KA13-12', 'KA14-1', 'KA14-2']

撰写回答