2012-01-24 30 views
10

Tôi đã có một danh sách sắp xếp của datetimes: (với khoảng cách ngày)danh sách chia của datetimes vào ngày

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

Và tôi muốn chia chúng vào một danh sách cho mỗi ngày:

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)] 
     ] 

Thuật toán, có thể đạt được ít nhất O (n).

Có lẽ giống như sau: (Điều này rõ ràng không xử lý bỏ qua ngày, và giọt dt cuối cùng, nhưng đó là một sự khởi đầu)

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 

Suy nghĩ?

+1

sử dụng một dict của danh sách với datetime_value .date() làm khóa. –

Trả lời

12

Cách đơn giản nhất để đi là sử dụng dict.setdefault đến mục nhóm rơi vào cùng một ngày và sau đó vòng lặp trong ngày thấp nhất đến cao nhất:

>>> 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)]] 

Một cách tiếp cận để làm cho nhóm này là itertools.groupby. Nó được thiết kế cho các loại hình công việc, nhưng nó không cung cấp một cách để điền vào một danh sách rỗng trong nhiều ngày mất tích:

>>> 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 và toordinal là những cải tiến tốt đẹp trên câu trả lời của tôi. :-) –

+2

Thậm chí đơn giản hơn 'setdefault' có thể là' defaultdict' (từ 'bộ sưu tập'). – Amber

+0

Đẹp - cảm ơn! Tôi có thể tạo danh sách 'days' của tôi cùng lúc với' list_of_dts' của tôi, vì vậy nó sẽ siêu hiệu quả. –

4

Bạn có thể sử dụng itertools.groupby để dễ dàng xử lý các loại của các vấn đề:

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

Điều cần biết - cảm ơn! Nó không xử lý yêu cầu của một danh sách trống cho những ngày mất tích, mặc dù. –

+0

@ Alex Ahh, thực sự, tôi bằng cách nào đó đã không nhận ra điểm đó. – qiao

1

Khỏa lấp sự thiếu hụt:

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) 

Kết quả:

[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)] 

Giải pháp này không yêu cầu danh sách ngày giờ ban đầu được sắp xếp.

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] 

Bây giờ bạn có từ điển, trong đó ngày là khóa và giá trị là danh sách các ngày tương tự.

và nếu bạn đang thiết lập trên có một danh sách thay vì

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

nay quả là một danh sách liệt kê, nơi tất cả các ngày với cùng một ngày được nhóm lại với nhau

+2

'date.date() trong groupedByDay.keys()' là O (n). Bạn có thể thay thế nó bằng 'date.date() trong groupedByDay' không? đó là O (1). – reclosedev

+0

đã hoàn tất. Cảm ơn vì tiền hỗ trợ. Tôi vừa mới nhặt python .. học một cái gì đó mới mỗi ngày. – Lex

Các vấn đề liên quan