两个列表中的Python字典

两个列表中的Python字典,python,dictionary,Python,Dictionary,我有两个列表,一个是值列表,另一个是日期列表 我想创建一个以值和日期为键的字典。但许多值具有相同的“键”(日期)。在制作字典之前,我需要将具有相同日期(相同键)的值加在一起 两个列表的元素数相同,但日期列表中的某些值重复(因为每个日期都有多个值) 根据键(日期)对值进行分组(将它们添加到一起)的最佳方式是什么 清单的例子 dates = [datetime(2014, 2, 1, 0, 0),datetime(2014, 2, 1, 0, 0),datetime(2014, 2, 1, 0, 0

我有两个列表,一个是值列表,另一个是日期列表

我想创建一个以值和日期为键的字典。但许多值具有相同的“键”(日期)。在制作字典之前,我需要将具有相同日期(相同键)的值加在一起

两个列表的元素数相同,但日期列表中的某些值重复(因为每个日期都有多个值)

根据键(日期)对值进行分组(将它们添加到一起)的最佳方式是什么

清单的例子

dates = [datetime(2014, 2, 1, 0, 0),datetime(2014, 2, 1, 0, 0),datetime(2014, 2, 1, 0, 0),datetime(2014, 3, 1, 0, 0),datetime(2014, 3, 1, 0, 0)]

values = [2,7,4,8,4]

I want my dictionary to look like this:
dict = [datetime(2014, 2, 1, 0, 0):13,datetime(2014, 3, 1, 0, 0):8,datetime(2014, 3, 1, 0, 0):4]

如果您有重复日期,并且希望对重复键的值进行分组,请使用:

输出:

defaultdict(<class 'int'>, {datetime.datetime(2014, 2, 1, 0, 0): 13, datetime.datetime(2014, 3, 1, 0, 0): 12})
最后,可以使用默认值为0的dict.get:

d = {}
for dte, val in zip(dates,values):
    d[dte] = d.get(dte, 0) + val

defaultdict
将是最快的方法,因为它正是为此目的而设计的。

假设这是您的输入

>>> dates = ['2015-01-01', '2015-01-01', '2015-01-02', '2015-01-03']
>>> values = [10, 15, 10, 10]
结合这些价值观

>>> data = zip(dates, values)
[('2015-01-01', 10), ('2015-01-01', 15), ('2015-01-02', 10), ('2015-01-03', 10)]
聚合相同日期的值

>>> import itertools
>>> new_data = []
>>> for key, group in itertools.groupby(data, lambda x: x[0]):
        tmp = [key, 0]    #: '0' is the default value
        for thing in group:
            tmp[1] += thing[1]
    new_data.append(tmp)
打印
新数据

>>> new_data
[['2015-01-01', 25], ['2015-01-02', 10], ['2015-01-03', 10]]
现在构建最终词典

>>> dict(new_data)
{'2015-01-03': 10, '2015-01-02': 10, '2015-01-01': 25}

itertools
defaultdict
在这方面是非常不必要的。我认为这更简单,更容易阅读

dates = [datetime(2014, 2, 1, 0, 0),datetime(2014, 2, 1, 0, 0),datetime(2014, 2, 1, 0, 0),datetime(2014, 3, 1, 0, 0),datetime(2014, 3, 1, 0, 0)]
values = [2,7,4,8,4]

combined = {}
for (date,value) in zip(dates,values):
  if date in combined:
    combined[date] += value
  else:
    combined[date] = value

性能分析

我并不是说,
defaultdict
是一个糟糕的解决方案,我只是指出它需要更多的隐性知识才能使用而不会出现陷阱

然而,这并不是最快的解决方案

from collections import defaultdict
from datetime import datetime
import timeit

dates = [datetime(2014, 2, 1, 0, 0),datetime(2014, 2, 1, 0, 0),datetime(2014, 2, 1, 0, 0),datetime(2014, 3, 1, 0, 0),datetime(2014, 3, 1, 0, 0)]
values = [2,7,4,8,4]

def combine_default_dict(dates=dates,values=values):
  d = defaultdict(int)
  for dte, val in zip(dates, values):
      d[dte] += val
  return d

def combine_setdefault(dates=dates,values=values):
  d = {}
  for dte, val in zip(dates,values):
      d.setdefault(dte,0)
      d[dte] += val
  return d

def combine_get(dates=dates,values=values):
  d = {}
  for dte, val in zip(dates,values):
      d[dte] = d.get(dte, 0) + val
  return d

def combine_contains(dates=dates,values=values):
  d = {}
  for (date,value) in zip(dates,values):
    if date in d:
      d[date] += value
    else:
      d[date] = value
  return d

def time_them(number=100000):
  for func_name in [k for k in sorted(globals().keys()) if k.startswith('combine_')]:
    timer = timeit.Timer("{0}()".format(func_name),"from __main__ import {0}".format(func_name))
    time_taken = timer.timeit(number=number)
    print "{0} - {1}".format(time_taken,func_name)
收益率:

>>> time_them()
0.388070106506 - combine_contains
0.485766887665 - combine_default_dict
0.415601968765 - combine_get
0.472551822662 - combine_setdefault

我已经在两台不同的机器和python版本上试用过
combine\u default\u dict
以最慢的速度与
combine\u setdefault
竞争
combine\u contains
一直是最快的。添加值是什么意思?将它们添加到列表中,或简单的算术加法?使用代码来帮助您描述问题,例如,
a=[1,2,3]
b=['foo',bar']
,等等。您能展示一下您的字典是什么样子吗?只是一个小提示:
defaultdict
是一个类似字典的对象,它为,如果被访问的键没有值。很好,这是有效的,我只需将每个键的值加在一起,我就完成了:)谢谢you@LukaPerović,我为您的编辑而编辑,您可以+=您实际想要添加的值作为加法,我认为您的输出应该只有两个键,因为使用defaultdict的确切目的是很难阅读吗?@Padraiccnningham:我不是说它很难阅读,只是相对来说比较难
defaultdict
的行为需要隐式理解其实现。你必须明白,如果你问它一个键的值,你会得到默认值,同时用默认值实例化这个键。
from collections import defaultdict
from datetime import datetime
import timeit

dates = [datetime(2014, 2, 1, 0, 0),datetime(2014, 2, 1, 0, 0),datetime(2014, 2, 1, 0, 0),datetime(2014, 3, 1, 0, 0),datetime(2014, 3, 1, 0, 0)]
values = [2,7,4,8,4]

def combine_default_dict(dates=dates,values=values):
  d = defaultdict(int)
  for dte, val in zip(dates, values):
      d[dte] += val
  return d

def combine_setdefault(dates=dates,values=values):
  d = {}
  for dte, val in zip(dates,values):
      d.setdefault(dte,0)
      d[dte] += val
  return d

def combine_get(dates=dates,values=values):
  d = {}
  for dte, val in zip(dates,values):
      d[dte] = d.get(dte, 0) + val
  return d

def combine_contains(dates=dates,values=values):
  d = {}
  for (date,value) in zip(dates,values):
    if date in d:
      d[date] += value
    else:
      d[date] = value
  return d

def time_them(number=100000):
  for func_name in [k for k in sorted(globals().keys()) if k.startswith('combine_')]:
    timer = timeit.Timer("{0}()".format(func_name),"from __main__ import {0}".format(func_name))
    time_taken = timer.timeit(number=number)
    print "{0} - {1}".format(time_taken,func_name)
>>> time_them()
0.388070106506 - combine_contains
0.485766887665 - combine_default_dict
0.415601968765 - combine_get
0.472551822662 - combine_setdefault