【问题标题】:Sorting parallel lists in python - first item descending, second item ascending在python中对并行列表进行排序-第一项降序,第二项升序
【发布时间】:2017-02-17 18:50:54
【问题描述】:

我有两个列表 - 一个用于团队名称,第二个用于积分

我想在不丢失对应团队的情况下根据分数对它们进行排序。我在 SO 上找到了一些非常适合执行此操作的内容 - 它按降序(从多到少)按点对团队进行排序。

第二个列表中似乎没有排序。

编辑 - 原始数据

Teams       Pts
D Clark   0
D Dupuis   2
T Leach   2
J Schutz    0
C Hearder 2
R Pagani  0
M Cameron  2
B Hunter  0

这是我正在使用的:

pts, teams = zip(*sorted(zip(pts, teams), reverse=True))
i = 1
for team, num_pts in zip(teams, pts):
    standings = str(i) + '. ' + team + " ("  + num_pts + ")"
    print standings
    i += 1

结果如下:

1. T Leach (2)
2. M Cameron (2)
3. D Dupuis (2)
4. C Hearder (2)
5. R Pagani (0)
6. J Schutz (0)
7. D Clark (0)
8. B Hunter (0)

我要做的是在团队名称上添加一个额外的排序 - 所以如果有平局,那么它将按名称升序排序

像这样:

1. C Hearder (2)
2. D Dupuis (2)
3. M Cameron (2)
4. T Leach (2)
5. B Hunter (0)
6. D Clark (0)
7. J Schutz (0)
8. R Pagani (0)

【问题讨论】:

  • 你想用key参数排序调用,带有可调用,见stackoverflow.com/questions/3121979/…
  • 能否也显示原始数据?
  • 抱歉 - 对 Python 很陌生 - 不知道如何用我的两个列表修改它 - 我猜它们有点像元组。 lambda 是什么意思?
  • @thefourtheye - 当然我必须从我的 html 处理中转储它。等一下
  • 好的 - 添加原始数据顺序

标签: python list python-2.7 sorting


【解决方案1】:

这里有两个选择。您可以使用cmpkey 作为sorted 的参数。

使用cmp,您正在定义一个接受两个参数的函数,这两个值被比较。如果第一个参数小于第二个参数,则返回一个负数。如果它大于第二个,则返回一个正数。如果相等,则返回 0。

第一个使用cmp的例子:

pts = ['2', '2', '2', '2', '2', '0', '0', '0', '0']
teams = ['T Leach', 'M Cameron', 'D Dupuis', 'C Hearder', 'R Pagani',
         'J Schutz', 'D Clark', 'B Hunter']

def custom_cmp(x,y):
    return cmp(x[0], y[0]) or cmp(y[1], x[1])

pts, teams = zip(*sorted(zip(pts, teams), cmp=custom_cmp, reverse=True))

如果python or 运算符的计算结果为True(不是如上所述的0),它将返回左侧,否则它将返回右侧。因此,如果这些点不相等,则此 custom_cmp 返回从 xy 的点的比较。否则,它将比较从yx 的团队(相反的顺序)。

另一方面,使用key,您只是在考虑如何单独查看一个元素,以便python 自然地了解如何按照您的需要对其进行排序。我们知道第一项正在正确比较,所以现在我们只需要翻转第二项。数字很​​容易,我们可以取负数。但是如何翻转字符串?

一种方法是获取字符串中每个字符的ord(应该是字符串的ascii 值整数)。然后您可以将 这些 值的负数打包成一个tuple。这就是其中之一的样子:

>>> tuple(-ord(c) for c in 'C Hearder')
(-67, -32, -72, -101, -97, -114, -100, -101, -114)

第二个使用key的例子:

def custom_key(pair):
    pts, team = pair
    return (pts, tuple(-ord(c) for c in team))

pts, teams = zip(*sorted(zip(pts, teams), key=custom_key, reverse=True))

回顾性编辑:

如果我们要定义一个自定义 key,我们也可以反转 key 本身并删除 reverse 参数:

def custom_key(pair):
    pts, team = pair
    return (-int(pts), team)

pts, teams = zip(*sorted(zip(pts, teams), key=custom_key))

【讨论】:

  • 谢谢 - 太完美了 - 效果很好。那么一切都是基于 cmp 函数的吗?这对字符串和数字都有效?
  • 避免使用cmp,使用key函数。效率低下。
  • 太好了,你明白它在做什么吧?如果计算结果为True,python or 运算符将返回左侧,否则将返回右侧。所以custom_cmp 返回从xy 的点的比较,如果点不相等的话。否则,它将比较 yx 中的名称(相反的顺序)。
  • @thefourtheye 你不需要仅仅因为它效率低下就避免使用它。我很少受到简单脚本中计算效率的限制。有时,易于表达胜过计算时间。但是,如果您想改用key 来写答案,请随意。
  • @dbmitch 我已经大大扩展了解释,如果你只是在学习这些东西是如何工作的,你可能会发现它们很有趣。
【解决方案2】:

您可以通过传入key kwarg 来指定sorted 的排序方式。使用key 的一种方便方法是使用operator 模块中的itemgetter

例如,如果您有一个元组列表(例如通过压缩两个列表)并且您想按第二项排序,那么第一项,键将是 itemgetter(1,0),因此您可以执行以下操作:

from operator import itemgetter
teams_and_points = zip(teams, pts)
for team, points in sorted(points_and_teams, key=itemgetter(1, 0)):
    print(team, points)

【讨论】:

  • 排序顺序在哪里发挥作用?是不是key=itemgetter(1, 0))倒序排列第二项,然后升序排列第一项?
  • 问题是关于如何通过一个升序和另一个降序进行排序。
  • key=lamdba x: (-x[1], x[0])
  • 我确信有办法做到这一点。就像@thefourtheye 建议的那样。
  • @thefourtheye 你不能接受字符串的负数
猜你喜欢
  • 2022-01-15
  • 1970-01-01
  • 2020-11-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-18
  • 2021-11-11
  • 2016-10-18
相关资源
最近更新 更多