基于2个键删除字典列表中的重复字典

时间:2017-05-01 19:57:56

标签: python list dictionary duplicates

我有一个字典列表,如下所示:

   my_list = [{'key1':'1', 'date':'2015-01-09'}, {'key1':'3', 'date':'2015-01-09'}, {'key1':'1', 'date':'2014-03-19'}, \
       {'key1':'4', 'date':'2015-05-09'} ,...]

在某些字典中,key1的值会重复,我想根据日期(字典的另一个键)从列表中删除它们,并且只保留具有最早日期的字典。 结果:

    my_list = [{'key1':'3', 'date':'2015-01-09'}, {'key1':'1', 'date':'2014-03-19'}, {'key1':'4', 'date':'2015-05-09'} ,...]

表现很重要。

5 个答案:

答案 0 :(得分:5)

我会使用key1作为字典理解中的关键重建字典,使用排序值(反向),以便最后返回最早的日期,覆盖相同的键:只保留最早的日期:

my_list = [{'key1':'1', 'date':'2015-01-09'}, {'key1':'3', 'date':'2015-01-09'}, {'key1':'1', 'date':'2014-03-19'}, \
       {'key1':'4', 'date':'2015-05-09'}]

my_dict = {d["key1"]:d for d in sorted(my_list,key=lambda l:l["date"],reverse=True)}

print(list(my_dict.values()))

结果(我认为排序没关系,否则我不能使用字典,因为订单没有保留):

[{'key1': '1', 'date': '2014-03-19'}, {'key1': '3', 'date': '2015-01-09'}, {'key1': '4', 'date': '2015-05-09'}]

(请注意,使用字典顺序对日期进行排序是正常的,因为它们是YYYY-MM-DD格式,它使事情变得更容易:无需解析日期)

如果内存不足,另一种解决方案是避免排序部分,因为它预先创建了列表的排序副本(不重复数据,但仍然可以占用一些内存)。

在这种情况下,经典循环可以做得更慢但内存更少(并且不需要排序)。当密钥不在目标词典中时,使用带有默认值的get返回'A'以强制插入(A排名高于任何数字)。

my_dict = {}

for l in my_list:
    k = l['key1']
    d = l['date']

    if my_dict.get(k,'A') > d:
        my_dict[k] = d

答案 1 :(得分:1)

这两个答案都有效,我想虽然当我是一个真正的初学者时,我会更喜欢一些更简单的东西。我会做的与@ Jean_Francois的答案相似,但我觉得有点简单(虽然它有更多的代码行)

我会从列表中构建一个字典,当我添加它时,我会检查日期。他指出,数据检查很简单

from collections import defaultdict
min_date_dict = defaultdict(dict)
for item_date in my_list:
    key = item_date['key1']
    date = item_date['date']
    if key in min_date:
          if min_date[key]['date'] > date:
                min_date[key] = item_date
    else:
       min_date[key] = item_date

此转换将您的项目放入字典中,并将键作为key1的值

defaultdict(<type 'dict'>, {'1': {'date': '2014-03-19', 'key1': '1'}, '3': {'date': '2015-01-09', 'key1': '3'}, '4': {'date': '2015-05-09', 'key1': '4'}})

现在把它放回一个列表

item_date_list = min_date.values()

答案 2 :(得分:0)

import pandas as pd

list(pd.DataFrame(my_list).sort_values(by='date').drop_duplicates(subset=['key1'], keep='first').apply(lambda s: s.to_dict(), axis=1).values)

答案 3 :(得分:0)

这是一种更详细的方法

my_list = [{'key1':'1', 'date':'2015-01-09'}, 
           {'key1':'3', 'date':'2015-01-09'}, 
           {'key1':'1', 'date':'2014-03-19'},
           {'key1':'4', 'date':'2015-05-09'}]

mins = {}
for i, d in enumerate(my_list):
    if d['key1'] not in mins or mins[d['key1']]['date'] > d['date']:
            mins[d['key1']] = {'date': d['date'], 'ind': i}

indices = sorted([d['ind'] for d in mins.values()])
filtered = [my_list[i] for i in indices]
print(filtered)

答案 4 :(得分:0)

您可以使用itertools groupby按键分组,然后获取每个组的最小日期。见下面的例子

final_list = [min(list(g), key = lambda x: x['date']) for k, g in groupby(sorted(my_list, key=lambda x: x['key1']), lambda x: x['key1'])]

结果

[{'date': '2014-03-19', 'key1': '1'}, {'date': '2015-01-09', 'key1': '3'}, {'date': '2015-05-09', 'key1': '4'}]