【问题标题】:Trying to sort a list of tuples in python first by date then by greatest number尝试首先按日期对python中的元组列表进行排序,然后按最大数排序
【发布时间】:2016-09-04 09:52:14
【问题描述】:

我有一个元组列表,我正在尝试按日期排序,然后按最大数排序。所以基本上当你有两个相同的日期时,它会将具有最大数字的元组放在第一位。请参见下面的示例。

我的元组列表

dataLst = [["Mike", 50, "08/10/2016"], ["Bob", 100, "08/10/2016"], ["Dave", 500, "08/01/2016"], ["Paul", -50, "08/20/2016"], ["Sam", 250, "08/30/2016"]]

然后我按元组中的日期对列表进行排序。

sDataLst = sorted(dataLst, key=operator.itemgetter(2))

然后我按数字倒序对排序后的列表进行排序。

sorted(sDataLst,key=operator.itemgetter(1), reverse=True) 

当我打印排序列表时,我得到以下信息。

print sDataLst

[['Dave', 500, '08/01/2016'], ['Mike', 50, '08/10/2016'], ['Bob', 100, '08/10/2016'], ['Paul', -50, '08/20/2016'], ['Sam', 250, '08/30/2016']]

如果您查看列表中具有相同日期的第二项和第三项,则应将它们颠倒,因为第三项中的数字大于第二项中的数字。我正在寻找的结果如下。

[['Dave', 500, '08/01/2016'], ['Bob', 100, '08/10/2016'], ['Mike', 50, '08/10/2016'], ['Paul', -50, '08/20/2016'], ['Sam', 250, '08/30/2016']]

对此的任何帮助将不胜感激。

谢谢

【问题讨论】:

  • 您知道以 mm/dd/yyyy 格式对日期进行排序不会像 日期顺序 这样,对吧?
  • 是的,我知道这一点,但因为我选择 mm/dd/yyyy,所以当作为字符串值传递时,它会正确排序。但谢谢你的注意。我会牢记这一点。
  • 好吧,不......他们不会正确排序......12/31/2015不会在01/01/2016之前出现吗?

标签: python list sorting


【解决方案1】:

由于顺序 mm/dd/yyyy,您无法将日期作为字符串进行比较,您可以使用 datetime 来:

from datetime import datetime
strp = datetime.strptime

srted = sorted(dataLst, key=lambda sub: (strp(sub[2],"%m/%d/%Y"), -sub[1]))

或者只是将日期的顺序拆分并反转​​为yyyy,mm,dd:

def iso(sub):
    mm, dd, yy = sub.split("/")
    return yy, mm, dd

srted = sorted(dataLst, key=lambda sub: (iso(sub[2]), -sub[1]))

两者都给你相同的输出:

 In [24]: sorted(dataLst, key=lambda sub: (iso( sub[2]), -sub[1]))Out[24]: 
[['Dave', 500, '08/01/2016'],
 ['Bob', 100, '08/10/2016'],
 ['Mike', 50, '08/10/2016'],
 ['Paul', -50, '08/20/2016'],
 ['Sam', 250, '08/30/2016']]

In [25]: sorted(dataLst, key=lambda sub: (strp(sub[2],"%m/%d/%Y"), -sub[1]))

Out[25]: 
[['Dave', 500, '08/01/2016'],
 ['Bob', 100, '08/10/2016'],
 ['Mike', 50, '08/10/2016'],
 ['Paul', -50, '08/20/2016'],
 ['Sam', 250, '08/30/2016']]

不同之处在于拆分速度更快,如下所示:

In [28]: timeit  sorted(dataLst, key=lambda sub: (strp(sub[2],"%m/%d/%Y"), -sub[1]))
10000 loops, best of 3: 66.4 µs per loop

In [29]: timeit sorted(dataLst, key=lambda sub: (iso( sub[2]), -sub[1]))
100000 loops, best of 3: 4.97 µs per loop

【讨论】:

  • 不应该是-sub[1],它在这里使用元组很好地工作,但当您有不同类型或更复杂的排序时就不那么有用了......:p(需要 Bob 在 Mike 之前...... .)
  • @NinjaPuppy,没有意识到他们想扭转关系的排序,我专注于比较日期完全错误的事实。固定;)
【解决方案2】:

您需要颠倒排序的顺序 - “决胜局”在“主”排序之前完成,因为 Python 的排序是稳定的,所以它们在按主顺序排序时保留决胜局的顺序,例如:

from datetime import datetime
from operator import itemgetter

dataLst = [["Mike", 50, "08/10/2016"], ["Bob", 100, "08/10/2016"], ["Dave", 500, "08/01/2016"], ["Paul", -50, "08/20/2016"], ["Sam", 250, "08/30/2016"]]
# Sort the tie breaker first
dataLst.sort(key=itemgetter(1), reverse=True)
# Sort on the main key - here we'll use `strptime` to sort as a proper date
dataLst.sort(key=lambda L: datetime.strptime(L[2], '%m/%d/%Y'))

这给出了:

[['Dave', 500, '08/01/2016'],
 ['Bob', 100, '08/10/2016'],
 ['Mike', 50, '08/10/2016'], # Bob and Mike properly ordered...
 ['Paul', -50, '08/20/2016'],
 ['Sam', 250, '08/30/2016']]

【讨论】:

  • 谢谢忍者小狗。
【解决方案3】:

类似于@Ninja Puppy 的回答,但在一次迭代中,不是两次:

dataLst.sort(key=lambda l: (datetime.strptime(l[2], '%m/%d/%Y'), -l[1]))

【讨论】:

  • 糟糕,我没有阅读他的回答。我想说同样的话太长了:)
猜你喜欢
  • 2023-03-25
  • 1970-01-01
  • 1970-01-01
  • 2021-12-28
  • 1970-01-01
  • 2011-02-17
  • 2018-05-30
  • 2023-03-05
  • 2019-09-25
相关资源
最近更新 更多