繁体   English   中英

根据2个键在词典列表中删除重复的词典

[英]Removing repeated dictionaries in a list of dictionaries based on 2 keys

我有一个字典列表,像这样:

   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'} ,...]

性能很重要。

我将使用排序后的值(反转)重建带有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

这两个答案都有效,我想虽然我是一个真正的初学者,但我宁愿选择一些简单的方法。 我会做的事情与@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

此转换将您的项目放入以key为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()
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)

这是一种更详细的方法

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)

您可以使用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'}]

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM