【问题标题】:How to return a list of tuples with unique elements based on maximum values?如何根据最大值返回具有唯一元素的元组列表?
【发布时间】:2017-12-21 06:31:11
【问题描述】:

我想返回具有唯一 ID 的元组列表,但特别保留最近日期的元组。

唯一 ID 位于每个元组的第一个元素中(即 1,2,3,4)。

日期存在于每个元组的多个元素中(元组的第 3 个元素和第 6 个元素)。

a = [(1,'Y', 'rat', datetime.datetime(2016, 12, 12, 0, 0), 'N', None),
(2,'Y', 'ox', datetime.datetime(2017, 9, 4, 0, 0), 'N', None),
(1,'N', None, None, 'Y', datetime.datetime(2017, 9, 17, 0, 0)),
(2,'N', None, None, 'Y', datetime.datetime(2017, 3, 16, 0, 0)),
(3,'Y', 'tiger', datetime.datetime(2013, 1, 18, 0, 0), 'N', None),
(4,'N', None, None, 'Y', datetime.datetime(2017, 10, 3, 0, 0))]

我期望的输出是:

b = [(1,'N', None, None, 'Y', datetime.datetime(2017, 9, 17, 0, 0)),
(2,'Y', 'ox', datetime.datetime(2017, 9, 4, 0, 0), 'N', None),
(3,'Y', 'tiger', datetime.datetime(2013, 1, 18, 0, 0), 'N', None),
(4,'N', None, None, 'Y', datetime.datetime(2017, 10, 3, 0, 0))]

我已将元组放入字典并使用 groupby 进行排序。

from itertools import groupby
dict={}
f = lambda x: x[0]
for key, group in groupby(sorted(a, key=f),f):
    dict[key] = list(group)

这是字典输出:

{1: [(1, 'Y', 'rat', datetime.datetime(2016, 12, 12, 0, 0), 'N', None), 
(1, 'N', None, None, 'Y', datetime.datetime(2017, 9, 17, 0, 0))], 
2: [(2, 'Y', 'ox', datetime.datetime(2017, 9, 4, 0, 0), 'N', None), 
(2, 'N', None, None, 'Y', datetime.datetime(2017, 3, 16, 0, 0))], 
3: [(3, 'Y', 'tiger', datetime.datetime(2013, 1, 18, 0, 0), 'N', None)], 
4: [(4, 'N', None, None, 'Y', datetime.datetime(2017, 10, 3, 0, 0))]}

从这一步开始,我无法将想要的字典值提取到新列表中。

提前感谢您的帮助!

【问题讨论】:

  • 欢迎来到stackoverflow!如果您提供您为解决问题而编写的代码的 sn-p,您更有可能从社区获得帮助。
  • “保留最近日期的元组”是什么意思?放在哪里?
  • 这可能密切相关:stackoverflow.com/questions/3922644/…
  • @sam-pyt 我想将元组放入一个新列表 - 抱歉不清楚,我将编辑我的问题以使其更清晰。
  • mfn,您的 ids 是小数字还是可以是任何数字?

标签: python


【解决方案1】:

首先,您可以定义一个函数来从元组中获取datetime,而不管其位置如何。 然后你可以按 id 和 datetime 对列表进行反向排序,按 ID 分组,获取下一个条目,然后再次排序(所以它是按 ID 排序的)。

>>> getdate = lambda t: next(x for x in t if isinstance(x, datetime.datetime))
>>> sorted(next(g) for k, g in itertools.groupby(sorted(a, key=lambda t: (t[0], getdate(t)), reverse=True), key=lambda t: t[0]))
[(1, 'N', None, None, 'Y', datetime.datetime(2017, 9, 17, 0, 0)),
 (2, 'Y', 'ox', datetime.datetime(2017, 9, 4, 0, 0), 'N', None),
 (3, 'Y', 'tiger', datetime.datetime(2013, 1, 18, 0, 0), 'N', None),
 (4, 'N', None, None, 'Y', datetime.datetime(2017, 10, 3, 0, 0))]

或者更短一点,只按 ID 排序一次,然后按日期获取 max;结果相同:

>>> [max(g, key=getdate) for k, g in itertools.groupby(sorted(a), key=lambda t: t[0])]

当然,使用简单的循环和字典也可以(而且更快)...

d = dict()
for t in a:
    if t[0] not in d or getdate(d[t[0]]) < getdate(t):
        d[t[0]] = t

...但是,没有什么能比得上过于复杂的单线了!

【讨论】:

    【解决方案2】:

    取决于我,您需要编写自定义代码。 python中没有内置函数可以做你想要实现的。

    您可以使用经典的 Python 代码或更多面向数据的库,例如 Pandas。

    主要思路就是这个

    result = dict()
    
    for item in a:
      if item[0] not in result:
         result[item[0]] = ...
      else:
         if result[item[0]][5] < item[5]:
            result[item[0]] = ...
    

    我不做细节,这只是全局和通用的想法。

    【讨论】:

    • 日期并不总是在[5]的位置。如果您愿意,请随意使用我的 getdate 函数将其与您的 dict 方法结合起来。
    • 我不打算为你做这项工作。我只是想为您提供必要的知识或可行的方法来满足您的需求。
    【解决方案3】:

    你可以试试这个:

    import datetime
    import itertools
    a = [(1,'Y', 'rat', datetime.datetime(2016, 12, 12, 0, 0), 'N', None),
     (2,'Y', 'ox', datetime.datetime(2017, 9, 4, 0, 0), 'N', None),
     (1,'N', None, None, 'Y', datetime.datetime(2017, 9, 17, 0, 0)),
     (2,'N', None, None, 'Y', datetime.datetime(2017, 3, 16, 0, 0)),
     (3,'Y', 'tiger', datetime.datetime(2013, 1, 18, 0, 0), 'N', None),
     (4,'N', None, None, 'Y', datetime.datetime(2017, 10, 3, 0, 0))]
    new_s = [d for c, d in [(a, sorted(list(b), key=lambda x:[h for h in x if type(h) == type(datetime.datetime(2017, 9, 17, 0, 0))][0], reverse=True)[0]) for a, b in itertools.groupby(sorted(a, key=lambda x:x[0]), key=lambda x:x[0])]]
    

    输出:

    [(1, 'N', None, None, 'Y', datetime.datetime(2017, 9, 17, 0, 0)), (2, 'Y', 'ox', datetime.datetime(2017, 9, 4, 0, 0), 'N', None), (3, 'Y', 'tiger', datetime.datetime(2013, 1, 18, 0, 0), 'N', None), (4, 'N', None, None, 'Y', datetime.datetime(2017, 10, 3, 0, 0))]
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-09-24
      • 1970-01-01
      • 2016-09-03
      • 2015-03-14
      • 1970-01-01
      相关资源
      最近更新 更多