Python 如何基于dict属性唯一地合并dict列表

Python 如何基于dict属性唯一地合并dict列表,python,django,Python,Django,我有两个Django查询集,我想根据它的日期属性合并它们。其实这不是Django的问题,但我会尽量解释清楚。 我需要根据两个数据属性对条目进行分组。假设我有一个模型: class User(models.Model): start_date = models.DateField(blank=True, null=True) end_date = models.DateField(blank=True, null=True) ... 现在我需要按月对这些条目进行分组(20

我有两个Django查询集,我想根据它的日期属性合并它们。其实这不是Django的问题,但我会尽量解释清楚。
我需要根据两个数据属性对条目进行分组。假设我有一个模型:

class User(models.Model):
    start_date = models.DateField(blank=True, null=True)
    end_date = models.DateField(blank=True, null=True)
    ...
现在我需要按月对这些条目进行分组(2010年5月开始的用户数量等):

我对
结束日期有相同的查询:

truncate_end_date = connection.ops.date_trunc_sql('month', 'end_date')
report_end = Employee.objects.exclude(end_date__isnull=True)\
   .extra({'month': truncate_end_date}).values('month')\
   .annotate(end_count=Count('pk')).order_by('-month')
现在这就是
报告\u start
的样子:

[{'start_count': 33, 'month': datetime.datetime(2016, 5, 1, 0, 0, tzinfo=<UTC>)}, 
{'start_count': 79, 'month': datetime.datetime(2016, 4, 1, 0, 0, tzinfo=<UTC>)}, 
{'start_count': 72, 'month': datetime.datetime(2016, 3, 1, 0, 0, tzinfo=<UTC>)},
... ]
我能想到的是把它改成dict,然后再改回dict列表。但我相信这不是一个非常优雅的解决方案,必须有一个更好的方法来编写这个python方式。
有什么想法吗?这是我的代码:

d = dict()
for end in report_end:
    d[end['month']] = {"end_count": end['end_count']}
for start in report_start:
    if start['month'] in d.keys():
        d[start['month']]["start_count"] = start['start_count']
    else:
        d[start['month']] = {"start_count": start['start_count']}
result = []
for key, i in d.items():
    result.append({'month': key,
                   'start_count': i['start_count'] if 'start_count' in i.keys() else None,
                   'end_count': i['end_count'] if 'end_count' in i.keys() else None}) 

datetime
是可散列的,因此您可以将其存储为
dict
的键并轻松合并。下面是一个使用
itemgetter
的更简洁的解决方案。这假设您的时间戳在每个
dict
s列表中是唯一的

from operator import itemgetter
import datetime


starts = [
{'start_count': 33, 'month': datetime.datetime(2016, 5, 1, 0, 0)}, 
{'start_count': 79, 'month': datetime.datetime(2016, 4, 1, 0, 0)}, 
{'start_count': 72, 'month': datetime.datetime(2016, 3, 1, 0, 0)}
]

# dummy data
ends = [
{'end_count': 122, 'month': datetime.datetime(2016, 5, 1, 0, 0)}, 
{'end_count': 213, 'month': datetime.datetime(2016, 4, 1, 0, 0)}, 
{'end_count': 121, 'month': datetime.datetime(2016, 3, 1, 0, 0)}
]


starts = dict(map(itemgetter('month', 'start_count'), starts))
ends = dict(map(itemgetter('month', 'end_count'), ends))


joined = [{'month': m, 'start_count': s,  'end_count': ends.get(m, None)}
    for m, s in starts.items()]

很好的解决方案。如果在结束时有一个
,而在开始时没有该月,该怎么办?它会在加入列表中吗?不,您可以修改如下:取月份键的并集,迭代列表理解和使用中的键。开始吧。好的,谢谢。我原以为用更少的行数编写一些itertools函数会很容易,但这也很好!
d = dict()
for end in report_end:
    d[end['month']] = {"end_count": end['end_count']}
for start in report_start:
    if start['month'] in d.keys():
        d[start['month']]["start_count"] = start['start_count']
    else:
        d[start['month']] = {"start_count": start['start_count']}
result = []
for key, i in d.items():
    result.append({'month': key,
                   'start_count': i['start_count'] if 'start_count' in i.keys() else None,
                   'end_count': i['end_count'] if 'end_count' in i.keys() else None}) 
from operator import itemgetter
import datetime


starts = [
{'start_count': 33, 'month': datetime.datetime(2016, 5, 1, 0, 0)}, 
{'start_count': 79, 'month': datetime.datetime(2016, 4, 1, 0, 0)}, 
{'start_count': 72, 'month': datetime.datetime(2016, 3, 1, 0, 0)}
]

# dummy data
ends = [
{'end_count': 122, 'month': datetime.datetime(2016, 5, 1, 0, 0)}, 
{'end_count': 213, 'month': datetime.datetime(2016, 4, 1, 0, 0)}, 
{'end_count': 121, 'month': datetime.datetime(2016, 3, 1, 0, 0)}
]


starts = dict(map(itemgetter('month', 'start_count'), starts))
ends = dict(map(itemgetter('month', 'end_count'), ends))


joined = [{'month': m, 'start_count': s,  'end_count': ends.get(m, None)}
    for m, s in starts.items()]