过滤列表中的最新项目

时间:2013-12-30 17:01:44

标签: python list dictionary lambda

我在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的过滤器,但无济于事。

3 个答案:

答案 0 :(得分:3)

如果记录已经“分组”在一起,即要选择的记录是相邻的,您只需使用itertools.groupbymax()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

如果您要求“数据”和“版本”字段都相同,请将调用更改为groupbygroupby(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
相关问题