我在Python中有这个大型数据结构 - 基本上是一个字典列表。这些词典中的每一个都可能包含一些重复属性和时间戳。我试图看看这些属性的值是否相同,如果是这样,只抓住具有最新时间戳的字典。例如:
[{'data': '3.50.1', 'date_time': '20131213-100308', 'version': '8.0.22'},
{'data': '3.50.1', 'date_time': '20131230-100308', 'version': '8.0.22'},
{'data': '3.47.0', 'date_time': '20131213-150410', 'version': '8.0.21'}]
字典中包含更多字段,但我们可以说这些字段可能会重复发生。在这种情况下,上面的列表应该过滤到只有两个序列 - 第二个和第三个。没有做双循环的任何聪明的方法来实现这个目标吗?
我尝试使用lambda函数并使用Python的过滤器,但无济于事。
答案 0 :(得分:3)
如果记录已经“分组”在一起,即要选择的记录是相邻的,您只需使用itertools.groupby,max()
和key = lambda rec: rec['date_time']
选择最近的记录每个组(请注意时间戳表示为字符串的方式,可以方便地按字典顺序进行比较):
from itertools import groupby
recs = [{'data': '3.50.1', 'date_time': '20131213-100308', 'version': '8.0.22'},
{'data': '3.50.1', 'date_time': '20131230-100308', 'version': '8.0.22'},
{'data': '3.47.0', 'date_time': '20131213-150410', 'version': '8.0.21'}]
filtered_recs = []
for key, group_iter in groupby(recs, lambda rec: rec['data']):
recent_rec = max(group_iter, key = lambda rec: rec['date_time'])
filtered_recs.append(recent_rec)
filtered_recs
=>
[{'data': '3.50.1', 'date_time': '20131230-100308', 'version': '8.0.22'},
{'data': '3.47.0', 'date_time': '20131213-150410', 'version': '8.0.21'}]
如果它们尚未组合在一起,您可以先对它们进行排序(可能效率低下),例如:
recs.sort(key=lambda rec: rec['data'])
或者,在上述解决方案中使用此替代方法,非类似于itertools,groupby
替代itertools.groupby
:
def groupby(seq, func):
groups = {}
for x in seq:
y = func(x)
groups.setdefault(y, []).append(x)
return groups
如果您要求“数据”和“版本”字段都相同,请将调用更改为groupby
:groupby(recs, lambda rec: (rec['data'], rec['version']) ):
答案 1 :(得分:1)
尝试这样的事情
def findLatestDict(lst):
latestDict = lst[0]
latestTime = latestDict["date_time"]
sameTimeList = []
for aDict in lst:
if aDict["date_time"] > latestTime:
latestTime = aDict["date_time"]
latestDict = aDict
sameTimeList = []
elif aDict["date_time"] == latestTime:
sameTimeList.append(aDict)
return (latestDict, sameTimeList)
此函数将返回它找到的第一个带有最新时间戳的字典,以及具有相同时间戳的所有其他字典的列表。
答案 2 :(得分:0)
如果对数据进行了适当的排序,最好使用itertools.groupby 如果数据没有排序,你可以这样做:
data = [
{'data': '3.50.1', 'date_time': '20131213-100308', 'version': '8.0.22'},
{'data': '3.50.1', 'date_time': '20131230-100308', 'version': '8.0.22'},
{'data': '3.47.0', 'date_time': '20131213-150410', 'version': '8.0.21'},
]
def filtered(data):
temp = dict()
for row in data:
# decorate
stamp = row.pop('date_time')
key = tuple(sorted(row.items()))
# filter
if temp.get(key, '')<stamp:
temp[key] = stamp
# undecorate
for key, stamp in temp.items():
d = dict(key)
d['date_time'] = stamp
yield d
for row in filtered(data):
print row