Django:使用order_by对数值和字符串值进行排序

cpjpxq1n  于 2023-06-25  发布在  Go
关注(0)|答案(3)|浏览(151)

我的问题是,显然数据是由UTF-8代码排序的,因为它是一个Charfield,具有可预测的结果。它会这样对数据进行排序
我的数据是:

1,8,7,2a, 4, 2, 11, 10...

我想要这个有序列表:

1,2,2a,4,7,8,10,11 ..

我真的不知道我怎么能正确地订购这个。

jgovgodb

jgovgodb1#

natsort可以做魔法。这是我一直以来的最爱将它们放入列表并直接应用natsort。

from natsort import natsorted
re = [1,2,'2a',4,7,8,10,11]
print(natsorted(re))

你得到

[1, 2, '2a', 4, 7, 8, 10, 11]
sdnqo3pr

sdnqo3pr2#

将每个元素分成两对,将第一对转换为整数,然后按对排序:

$ ipython
Python 3.11.3 (main, Apr  7 2023, 19:30:05) [Clang 13.0.0 (clang-1300.0.29.30)]
Type 'copyright', 'credits' or 'license' for more information
IPython 8.10.0 -- An enhanced Interactive Python. Type '?' for help.

In [1]: its = '1,8,7,2a, 4, 2, 11, 10'.replace(' ', '').split(',')

In [2]: its
Out[2]: ['1', '8', '7', '2a', '4', '2', '11', '10']

In [3]: import re

In [4]: def convert(s: str) -> tuple[int, str]:
   ...:     i = 0
   ...:     if m := re.match(r'\d+', s):
   ...:         j = m.group()
   ...:         i = int(j)
   ...:         s = s[len(j):]
   ...:     return (i, s)
   ...:

In [5]: [convert(i) for i in its]
Out[5]: [(1, ''), (8, ''), (7, ''), (2, 'a'), (4, ''), (2, ''), (11, ''), (10, '')]

In [6]: sorted(its, key=lambda x: convert(x))
Out[6]: ['1', '2', '2a', '4', '7', '8', '10', '11']
xe55xuns

xe55xuns3#

你已经得到了两个纯Python解决方案。但是你提到的Django表明你想要一个在数据库内部工作的解决方案。
为此,我建议存储两个字段。一是原文。另一个是文本mangled,以便它按字母顺序排序,如你所愿。
例如,您可以获取任何数字字符串,然后使用固定长度的前导0存储它。所以你的名单

1, 8, 7, 2a, 4, 2, 11, 10...

成为

0000000000000001,
0000000000000008,
0000000000000007,
0000000000000002a,
0000000000000004,
0000000000000002,
0000000000000011,
0000000000000010,

按字母顺序排序为:

0000000000000001,
0000000000000002,
0000000000000002a,
0000000000000004,
0000000000000007,
0000000000000008,
0000000000000010,
0000000000000011,

对该字段进行排序将对记录进行排序,而对原始字段进行排序

1, 2, 2a, 4, 7, 8, 10, 11

但你要想想你要怎么做。我所描述的解决方案

2, 2.5, 2.52, 3

进入

0000000000000002,
0000000000000002.0000000000000005,
0000000000000002.0000000000000052,
0000000000000003,

这将排序为

2, 2.52, 2.5, 3

因此,添加一个浮动规则,现在您可以像这样对版本号进行排序:

v1.1, v1.10, v1.11, v1.9

只要你的用例需要,你就可以深入这个兔子洞。但要知道这是一个兔子洞。你的答案总是可以改进的。

相关问题