我想返回一个具有唯一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))]}
从这一步开始,我无法将我想要的字典值提取到新列表中。
提前感谢您的帮助!
答案 0 :(得分:4)
首先,您可以定义一个函数来从元组中获取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
......但是,嘿,没有什么能比一个过于复杂的单行语更胜一筹!
答案 1 :(得分:0)
在我看来,你需要编写自定义代码。 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]] = ...
我没有详细说明,这只是全球性和通用性的想法。
答案 2 :(得分:0)
你可以试试这个:
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))]