如何在python中排序列表字典时进行多重比较?

时间:2017-02-28 09:14:46

标签: python sorting dictionary

我有一份列表字典,summary

summary = {
    'Raonic': [2, 0, 11, 122, 16, 139],
    'Halep': [2, 2, 10, 75, 6, 60],
    'Kerber': [2, 0, 7, 68, 7, 71],
    'Wawrinka': [1, 2, 14, 133, 13, 128],
    'Djokovic': [2, 2, 10, 75, 8, 125],
}

我希望按照排名的降序打印到屏幕(标准输出)的摘要,其中排名按照该顺序中的条件1-6(比较项目1(列表的)),如果相等比较项目2(列表中的),如果它们相等,则比较项目3(列表中的项目3)。此比较将以降序继续到列表的第4项。

但是,列表的第5项和第6项的比较必须以升序完成。

输出:

Halep 2 2 10 75 6 60
Djokovic 2 2 10 75 8 125
Raonic 2 0 11 122 16 139
Kerber 2 0 7 68 7 71
Wawrinka 1 2 14 133 13 128

我的解决方案是:

for key, value in sorted(summary.items(), key=lambda e: e[1][0], reverse = True):
    print(key, end=' ')
    for v in value:
        print(v, end=' ')
    print()

但是我的解决方案只是成功地对列表的第1列进行排序。

访问this site for full question

1 个答案:

答案 0 :(得分:5)

对于数值,您可以否定该值以获得反向排序。对于您的排序键,返回一系列要排序的值,否定“对面”中的值。方向:

ranked = sorted(
    summary.items(),
    key=lambda kv: kv[1][:4] + [-kv[1][4], -kv[1][5]],
    reverse=True)

这会按排序顺序生成(key, value)个元组,因为字典是无序的。

对于('Halep', [2, 2, 10, 75, 6, 60]),排序键lambda返回[2, 2, 10, 75, -6, -60],确保在 'Djokovic'之前将其排序,其中排序键设置为{{1} },因为在反向排序顺序([2, 2, 10, 75, -8, -125])中,reverse=True-6之前排序。但是,前4列中任何值的差异都按另一个方向排序,因此第一列中-8或更多的任何内容都将在3之前排序,或以{{1}开头的任何内容排序或更高等等。

如果值不是数字,并且没有其他的反转'列可用的值选项,您必须对两次进行排序。首先是最后2列(按升序排序),然后是前4列(按降序排列,反之,顺序排列):

('Halep', [...])

这是因为Python的排序算法(称为Timsort)是 stable ,排序键完全相等的任何两个输入的相对顺序是不受影响的。因此,任何键 A B ,其中只有最后一列或两列不同,在2, 3中给出相对排序,然后不会改变在# non-numeric option part_sorted = sorted(summary.items(), key=lambda kv: kv[1][-2:]) ranked = sorted(part_sorted, key=lambda kv: kv[1][:4], reverse=True) 中,因为part_sorted订单未受影响。如果 A 在第一个排序中的 B 之后排序,那么第二个排序将在 B 之后留下 A