Python高级列表排序

时间:2013-10-04 11:29:28

标签: python list sorting

以下列表包含格式(ID,级别,值):

[(A, 1, None),
 (B, 1, None),
 (C, 1, None),
 (A, 2, 1.1),
 (B, 2, 5.0),
 (C, 2, 5.0),
 (C, 3, 40),
 (B, 3, 55)]

因此,问题是根据来自一个级别更低的值,使用相同的对具有相同级别的项目进行排序。如果下面的一个级别的值相等,则它会低于2级,依此类推。所以结束列表应如下所示:

[(A, 1, None),
 (C, 1, None), <- this moved up because @ lvl3 C['value'] < B['value']
 (B, 1, None),
 (A, 2, 1.1),
 (C, 2, 5.0), <- this moved up because @ lvl3 C['value'] < B['value']
 (B, 2, 5.0),
 (C, 3, 40),
 (B, 3, 55),]

有人可以建议一种算法来实现吗?顺便说一句,我总是得到按排序的起始列表,然后是 level

1 个答案:

答案 0 :(得分:5)

您需要一个查找表来确定每个(ID, level)元组的值。您需要将所有可能的级别查找添加到排序键:

# Lookup for values by (id, level)
values = {}
minlevel, maxlevel = float('inf'), float('-inf')
for id_, level, value in inputlist:
    values[id_, level] = value
    if level < minlevel:
        minlevel = level
    if level > maxlevel:
        maxlevel = level

def level_sort(tup):
    id_, level, value = tup
    sortkey = [level]
    for l in range(minlevel, maxlevel + 1):
        sortkey.append(values.get((id_, l)) if l >= level else None)
    return sortkey

sorted(inputlist, key=level_sort)

sort函数生成要排序的值列表,从它们自己级别的值开始(对于任何较低级别填充None)加上较高级别的相同ID的值。

例如,对于(B, 1, None)(C, 1, None)元组,sort函数输出:

>>> level_sort(('B', 1, None))
[1, None, 5.0, 55]
>>> level_sort(('C', 1, None))
[1, None, 5.0, 40]

其中只有最后一个值不同并确定最终的排序顺序。

为此,您需要首先了解输入列表中的最小和最大级别,因此需要更精细的地图构建循环。

演示:

>>> from pprint import pprint
>>> A, B, C = 'ABC'
>>> inputlist = [(A, 1, None),
...  (B, 1, None),
...  (C, 1, None),
...  (A, 2, 1.1),
...  (B, 2, 5.0),
...  (C, 2, 5.0),
...  (C, 3, 40),
...  (B, 3, 55)]
>>> values = {}
>>> minlevel, maxlevel = float('inf'), float('-inf')
>>> for id_, level, value in inputlist:
...     values[id_, level] = value
...     if level < minlevel:
...         minlevel = level
...     if level > maxlevel:
...         maxlevel = level
... 
>>> def level_sort(tup):
...     id_, level, value = tup
...     sortkey = [level]
...     for l in range(minlevel, maxlevel + 1):
...         sortkey.append(values.get((id_, l)) if l >= level else None)
...     return sortkey
... 
>>> pprint(sorted(inputlist, key=level_sort))
[('A', 1, None),
 ('C', 1, None),
 ('B', 1, None),
 ('A', 2, 1.1),
 ('C', 2, 5.0),
 ('B', 2, 5.0),
 ('C', 3, 40),
 ('B', 3, 55)]