2015-08-05 4 views
0

У меня есть два списка, один из них - это список значений, а другой - список дат.Python словарь из двух списков

Я хочу создать словарь со значениями и датами в виде ключей. Но многие значения имеют один и тот же «ключ» (дата). Мне нужно добавить значения с той же датой (тот же ключ) вместе, прежде чем делать словарь.

Оба списка имеют одинаковое количество элементов, но список дат имеет некоторые значения, дублированные (поскольку каждая дата имеет более одного значения).

Что было бы лучшим способом группировать значения (добавлять их вместе) на основе ключей (дат)?

Примеры списков

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] 
+1

Что значит добавить значения? добавить их в список или простое арифметическое дополнение? –

+3

Используйте код, который поможет вам описать проблему, например 'a = [1,2,3]', 'b = ['foo', 'bar']' и т. Д. –

+0

вы можете показать, как выглядит ваш словарь? –

ответ

1

Если повторяющиеся даты и хотите сгруппировать значения для повторяющихся ключей, используйте defaultdict:

from collections import defaultdict 
d = defaultdict(int) 
for dte, val in zip(dates, values): 
    d[dte] += val 

Выход:

defaultdict(<class 'int'>, {datetime.datetime(2014, 2, 1, 0, 0): 13, datetime.datetime(2014, 3, 1, 0, 0): 12}) 

Или используя обычный dict и dict.setdefault:

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

Наконец вы можете использовать dict.get со значением по умолчанию 0:

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

defaultdict будет самый быстрый подход, поскольку он предназначен именно для этой цели.

+0

Просто небольшое примечание: 'defaultdict' - это словарь-подобный объект, который устанавливает значение по умолчанию для, если ключ доступа не имеет значения. – user3255354

+0

Nice, это работает, мне нужно только добавить значения для каждого ключа, и я закончил :) Спасибо – Luka

+0

@ LukaPerović, я отредактировал для вашего редактирования, вы можете + = значения, которые вы на самом деле хотите добавить как кроме того, я думаю, что вы должны иметь только два ключа, хотя –

1

Предполагая, что, если это ваш вход,

>>> 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,

>>> 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} 
0

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 

Я попробовал его на несколько различных машин и версий питона. combine_default_dict конкурирует с combine_setdefault за самый медленный. combine_contains был последовательно самым быстрым.

+0

Использование значения defaultdict для того, что было предназначено для, трудно читать? –

+0

@PadraicCunningham: Я не говорю, что это трудно читать, просто более сложно. Поведение 'defaultdict' требует неявного понимания его реализации. Вы должны понимать, что если вы когда-либо спросите его о значении ключа, вы вернете значение по умолчанию и одновременно создадите этот ключ со значением по умолчанию. – MattH

Смежные вопросы