排序与字母混合的实数列表

时间:2012-04-24 22:43:18

标签: python django postgresql sorting

我有一个必须排序的数据列表,遗憾的是这些对象的命名方案不是很一致。数据是一个字符串列表,通常是实数,但有时最后会有一个字母。此列表中可接受值的一些示例如下所示:

# this is how it should be sorted
['1', '1.1', '1.2', '2', '2.1A', '2.1B', '2.2A', '101.1', '101.2']

由于这些是在数据库中,我首先想到的是使用以下django方法返回已排序的结果,但它返回如下。

#took out unneeded code
choices = [l.number for l in Locker.objects.extra(
               select={'asnumber': 'CAST(number as BYTEA)'}).order_by('asnumber')]
print choices
==> ['1', '1.1', '101.1', '101.2', '2', '2.1A', '2.1B', '2.2A']

遗憾的是,它无法对它进行排序。所以我的新计划是编写一个可以使用python sorted方法的方法,但我仍然不确定如何编写它。我需要找到一种方法,按字符串的实数部分排序,然后作为辅助排序,按附加到结尾的字母排序。

有关该去哪儿的建议吗?

5 个答案:

答案 0 :(得分:4)

让DBMS进行排序,这就是它非常擅长的。你几乎无法与你的应用程序中的性能相媲美。

如果你得到的只是附加A或B的小数,你可以简单地说:

SELECT *
FROM  (
   SELECT unnest(
    ARRAY['1', '1.1', '1.2', '2', '2.1A', '2.1B', '2.2A', '101.1', '101.2']) AS s
   ) x
ORDER  BY rtrim(s, 'AB')::numeric, s;

完全按照要求订购,也快速订购。 ARRAYunnest()的子选择仅用于构建快速测试用例。重要的是ORDER BY条款 - rtrim() in the manual

如果涉及其他字符,您可能需要更新问题以完成图片。

答案 1 :(得分:1)

x = ['1', '1.1', '1.2', '2', '2.1A', '2.1B', '2.2A', '101.1', '101.2']

#sort by the real number portion

import string

letters = tuple(string.ascii_letters)

def change(x):
    if x.endswith(letters):
        return float(x[:len(x) -1])
    else:
        return float(x)

my_list = sorted(x, key = lambda k: change(k))

结果:

>>> my_list
['1', '1.1', '1.2', '2', '2.1A', '2.1B', '2.2A', '101.1', '101.2']

答案 2 :(得分:0)

我在结尾处过早概括为任意数量的字母:

from itertools import takewhile

def sort_key(value):
    cut_point = len(value) - len(list(takewhile(str.isalpha, reversed(value))))
    return (float(value[:cut_point]), value[cut_point:])

sorted((
    l.number
    for l in Locker.objects.extra(select={'asnumber': 'CAST(number as BYTEA)'})
), key = sort_key)

答案 3 :(得分:0)

将字符串拆分为元组 - 实数(将其转换为浮点数或十进制数)和通常为空的字符串。如果你对元组进行排序,并使用python的内置排序(timesort),它应该非常快。

如果您的实物中允许使用科学记数法,请注意,例如1e10。

如果有任何机会,以后比较会有额外的复杂性,请使用类而不是元组。但元组可能会更快。然后定义一个或多个比较函数(取决于你是否在python 2.x或3.x中)。

元组比较元素0,然后是元素1,等等。

您的课程替代方法需要 cmp 方法或3.x等效方法。

答案 4 :(得分:0)

将字符串存储为字符串然后解析它以对其进行排序似乎是错误的方法。如果您真正拥有的是

  • 主要编号
  • 次要号码
  • 可选修订

然后我强烈建议将其存储为两个整数和一个文本字段。对major_number,minor_number进行排序,修订版将完全按预期工作。您可以将asnumber定义为数据库级别的视图,也可以将其定义为基于具有关联__cmp__()的三个基本数字的类。