2012-01-24 65 views
10

我有日期時間的排序列表:(含當天缺口)拆分日期時間的列表爲天

list_of_dts = [ 
       datetime.datetime(2012,1,1,0,0,0), 
       datetime.datetime(2012,1,1,1,0,0), 
       datetime.datetime(2012,1,2,0,0,0), 
       datetime.datetime(2012,1,3,0,0,0), 
       datetime.datetime(2012,1,5,0,0,0), 
       ] 

而且我想他們分流到列表中的每一天:

result = [ 
      [datetime.datetime(2012,1,1,0,0,0), datetime.datetime(2012,1,1,1,0,0)], 
      [datetime.datetime(2012,1,2,0,0,0)], 
      [datetime.datetime(2012,1,3,0,0,0)], 
      [], # Empty list for no datetimes on day 
      [datetime.datetime(2012,1,5,0,0,0)] 
     ] 

算法上,它應該是能夠實現至少爲O(n)。

也許類似如下: (這顯然不處理漏天,並丟棄最後的DT,但它是一個開始)

def dt_to_d(list_of_dts): 
    result = [] 
    start_dt = list_of_dts[0] 
    day = [start_dt] 
    for i, dt in enumerate(list_of_dts[1:]): 
     previous = start_dt if i == 0 else list_of_dts[i-1] 
     if dt.day > previous.day or dt.month > previous.month or dt.year > previous.year: 
      # split to new sub-list 
      result.append(day) 
      day = [] 
      # Loop for each day gap? 
     day.append(dt) 
    return result 

的思考?

+1

使用列表的字典與datetime_value列表.date()作爲鍵。 –

回答

12

去最簡單的方法是使用dict.setdefault墜落在同一天,然後遍歷最低一天最高組條目:

>>> import datetime 
>>> list_of_dts = [ 
       datetime.datetime(2012,1,1,0,0,0), 
       datetime.datetime(2012,1,1,1,0,0), 
       datetime.datetime(2012,1,2,0,0,0), 
       datetime.datetime(2012,1,3,0,0,0), 
       datetime.datetime(2012,1,5,0,0,0), 
       ] 

>>> days = {} 
>>> for dt in list_of_dts: 
     days.setdefault(dt.toordinal(), []).append(dt) 

>>> [days.get(day, []) for day in range(min(days), max(days)+1)] 
[[datetime.datetime(2012, 1, 1, 0, 0), datetime.datetime(2012, 1, 1, 1, 0)], 
[datetime.datetime(2012, 1, 2, 0, 0)], 
[datetime.datetime(2012, 1, 3, 0, 0)], 
[], 
[datetime.datetime(2012, 1, 5, 0, 0)]] 

作出這樣的分組另一種方法是itertools.groupby。它是專爲這方面的工作,但它並沒有提供一種方式來填補,在空列表失蹤天數:

>>> import itertools 
>>> [list(group) for k, group in itertools.groupby(list_of_dts, 
                key=datetime.datetime.toordinal)] 
[[datetime.datetime(2012, 1, 1, 0, 0), datetime.datetime(2012, 1, 1, 1, 0)], 
[datetime.datetime(2012, 1, 2, 0, 0)], 
[datetime.datetime(2012, 1, 3, 0, 0)], 
[datetime.datetime(2012, 1, 5, 0, 0)]] 
+1

setdefault和toordinal對我的回答有很好的改進。 :-) –

+2

甚至比'setdefault'簡單可以'defaultdict'(來自'collections')。 – Amber

+0

美麗 - 謝謝!我可以和我的'list_of_dts'同時生成'days'列表,所以它會非常高效。 –

4

您可以使用itertools.groupby輕鬆地處理這類問題:

import datetime 
import itertools 

list_of_dts = [ 
     datetime.datetime(2012,1,1,0,0,0), 
     datetime.datetime(2012,1,1,1,0,0), 
     datetime.datetime(2012,1,2,0,0,0), 
     datetime.datetime(2012,1,3,0,0,0), 
     datetime.datetime(2012,1,5,0,0,0), 
     ] 

print [list(g) for k, g in itertools.groupby(list_of_dts, key=lambda d: d.date())] 
+0

很高興知道 - 謝謝!儘管如此,它沒有處理空缺列表的要求。 –

+0

@Alex Ahh,事實上,我沒有注意到這一點。 – qiao

1

填充間隙:

date_dict = {} 
for date_value in list_of_dates: 
    if date_dict.has_key(date_value.date()): 
     date_dict[date_value.date()].append(date_value) 
    else: 
     date_dict[date_value.date()] = [ date_value ] 
sorted_dates = sorted(date_dict.keys()) 
date = sorted_dates[0] 
while date <= sorted_dates[-1]: 
    print date_dict.get(date, []) 
    date += datetime.timedelta(1) 

結果:

[datetime.datetime(2012, 1, 1, 0, 0), datetime.datetime(2012, 1, 1, 1, 0)] 
[datetime.datetime(2012, 1, 2, 0, 0)] 
[datetime.datetime(2012, 1, 3, 0, 0)] 
[] 
[datetime.datetime(2012, 1, 5, 0, 0)] 

此解決方案不需要對原始日期時間列表進行排序。

1
list_of_dts = [ 
      datetime.datetime(2012,1,1,0,0,0), 
      datetime.datetime(2012,1,1,1,0,0), 
      datetime.datetime(2012,1,2,0,0,0), 
      datetime.datetime(2012,1,3,0,0,0), 
      datetime.datetime(2012,1,5,0,0,0), 
      ] 

groupedByDay={} 
for date in list_of_dts: 
    if date.date() in groupedByDay: 
     groupedByDay[date.date()].append(date) 
    else: 
     groupedByDay[date.date()]=[date] 

現在你有一本字典,其中的日期是關鍵,值是一個類似的日期列表。

,如果你是在具有列表設置,而不是

result = groupedByDay.values() 
result.sort() 

現在的結果是列表,所有與當天日期組合在一起

+2

'groupedByDay.keys()'中的date.date()是O(n)。你可以用'groupedByDay'中的'date.date()替換它嗎?它是O(1)。 – reclosedev

+0

完成。謝謝你的提示。我剛剛拿起蟒蛇......每天學習新東西。 – Lex

相關問題