2016-01-14 76 views
2

我試圖合併重疊的日期時間範圍。我有日期時間範圍的列表,列表中的元組:如何在Python中正確合併重疊的日期時間範圍

data = [(datetime.datetime(2016, 1, 10, 13, 0), datetime.datetime(2016, 1, 10, 16, 0)), (datetime.datetime(2016, 1, 10, 14, 0), datetime.datetime(2016, 1, 10, 14, 0)), (datetime.datetime(2016, 1, 10, 22, 0), datetime.datetime(2016, 1, 10, 22, 0)), (datetime.datetime(2016, 1, 10, 23, 0), datetime.datetime(2016, 1, 11, 0, 30)), (datetime.datetime(2016, 1, 11, 2, 30), datetime.datetime(2016, 1, 11, 3, 30)), (datetime.datetime(2016, 1, 11, 13, 0), datetime.datetime(2016, 1, 11, 16, 0)), (datetime.datetime(2016, 1, 11, 14, 0), datetime.datetime(2016, 1, 11, 14, 0)), (datetime.datetime(2016, 1, 11, 20, 30), datetime.datetime(2016, 1, 11, 21, 30)), (datetime.datetime(2016, 1, 11, 22, 0), datetime.datetime(2016, 1, 11, 22, 0)), (datetime.datetime(2016, 1, 12, 2, 30), datetime.datetime(2016, 1, 12, 3, 30)), (datetime.datetime(2016, 1, 12, 13, 0), datetime.datetime(2016, 1, 12, 16, 0)), (datetime.datetime(2016, 1, 12, 14, 0), datetime.datetime(2016, 1, 12, 14, 0)), (datetime.datetime(2016, 1, 12, 19, 30), datetime.datetime(2016, 1, 12, 20, 30)), (datetime.datetime(2016, 1, 12, 22, 0), datetime.datetime(2016, 1, 12, 22, 0)), (datetime.datetime(2016, 1, 13, 2, 30), datetime.datetime(2016, 1, 13, 3, 30)), (datetime.datetime(2016, 1, 13, 13, 0), datetime.datetime(2016, 1, 13, 16, 0)), (datetime.datetime(2016, 1, 13, 14, 0), datetime.datetime(2016, 1, 13, 14, 0)), (datetime.datetime(2016, 1, 13, 20, 0), datetime.datetime(2016, 1, 13, 21, 0)), (datetime.datetime(2016, 1, 13, 21, 30), datetime.datetime(2016, 1, 13, 22, 0)), (datetime.datetime(2016, 1, 13, 22, 0), datetime.datetime(2016, 1, 13, 22, 0)), (datetime.datetime(2016, 1, 14, 2, 30), datetime.datetime(2016, 1, 14, 3, 30)), (datetime.datetime(2016, 1, 14, 13, 0), datetime.datetime(2016, 1, 14, 16, 0)), (datetime.datetime(2016, 1, 14, 14, 0), datetime.datetime(2016, 1, 14, 14, 0)), (datetime.datetime(2016, 1, 14, 22, 0), datetime.datetime(2016, 1, 14, 22, 0)), (datetime.datetime(2016, 1, 14, 22, 0), datetime.datetime(2016, 1, 14, 23, 0)), (datetime.datetime(2016, 1, 15, 2, 30), datetime.datetime(2016, 1, 15, 3, 30)), (datetime.datetime(2016, 1, 15, 13, 0), datetime.datetime(2016, 1, 15, 16, 0)), (datetime.datetime(2016, 1, 15, 14, 0), datetime.datetime(2016, 1, 15, 14, 0)), (datetime.datetime(2016, 1, 15, 20, 30), datetime.datetime(2016, 1, 15, 22, 0)), (datetime.datetime(2016, 1, 15, 22, 0), datetime.datetime(2016, 1, 15, 22, 0)), (datetime.datetime(2016, 1, 16, 2, 30), datetime.datetime(2016, 1, 16, 3, 30)), (datetime.datetime(2016, 1, 16, 13, 0), datetime.datetime(2016, 1, 16, 16, 0)), (datetime.datetime(2016, 1, 17, 2, 30), datetime.datetime(2016, 1, 17, 3, 30))] 

這裏是我當前的代碼:

import datetime 

def merge_date_ranges(data): 

    result = [] 

    for t1, t2 in ((data[i], data[i+1]) for i in range(len(data)-1)): 
     if t1[1] >= t2[0]: 
      result.append((min(t1[0], t2[0]), max(t1[1], t2[1]))) 
     else: 
      result.append(t1) 

如果T1(第1日期時間範圍),T2(第二日期時間範圍)不要再重複我只需將T1添加到新列表(結果)。如果T1和T2 DO重疊,則將合併的元組添加到新列表(結果)。

我的問題是合併後會發生什麼。例如:

T1 = (datetime.datetime(2016, 1, 10, 13, 0), datetime.datetime(2016, 1, 10, 16, 0)) 
T2 = (datetime.datetime(2016, 1, 10, 14, 0), datetime.datetime(2016, 1, 10, 14, 0)) 

T1和T2合併及以下添加到我的新名單:

(datetime.datetime(2016, 1, 10, 13, 0), datetime.datetime(2016, 1, 10, 16, 0)) 

所以現在我想我的代碼(在for循環的下一次迭代)比較合併後的元組(新T1)與下一日期時間範圍在我的名單:

T1 = (datetime.datetime(2016, 1, 10, 13, 0), datetime.datetime(2016, 1, 10, 16, 0)) 
T2 = (datetime.datetime(2016, 1, 10, 22, 0), datetime.datetime(2016, 1, 10, 22, 0)) 

但是,相反,這裏是T1和T2像:

T1 = (datetime.datetime(2016, 1, 10, 14, 0), datetime.datetime(2016, 1, 10, 14, 0)) 
T2 = (datetime.datetime(2016, 1, 10, 22, 0), datetime.datetime(2016, 1, 10, 22, 0)) 

和T1被添加到我的新列表(我不想),因爲它已經被合併過。

但我只是無法讓我的頭在如何做到這一點。如果我能夠通過用合併的元組替換T2並刪除T1來更新我的原始列表,那將會更容易。但據我所知,這是不可能的,甚至是一個好的做法。

在拉我的頭髮一個星期後,我在這裏發佈我的第一個問題,希望有人能幫助我恢復理智。 :)

更新 基本上我想結束一個沒有日期範圍重疊的新列表。

+0

相關:Python的 - 刪除重疊列表(http://stackoverflow.com/q/16312871/4279) – jfs

回答

1

我想這就是你想要的。 給它一個測試和評論:

def merge_date_ranges(data): 
    result = [] 
    t_old = data[0] 
    for t in data[1:]: 
     if t_old[1] >= t[0]: #I assume that the data is sorted already 
      t_old = ((min(t_old[0], t[0]), max(t_old[1], t[1]))) 
     else: 
      result.append(t_old) 
      t_old = t 
    else: 
     result.append(t_old) 
    return result 

我假設的日期已經排序。

順便說一句,我發現唯一不可思議的日子是獨身日子,也許你應該修正你的輸入數據。

salida = merge_date_ranges(data) 
for item in [t for t in data if t not in salida]: 
    print item 

(datetime.datetime(2016, 1, 10, 14, 0), datetime.datetime(2016, 1, 10, 14, 0)) 
(datetime.datetime(2016, 1, 11, 14, 0), datetime.datetime(2016, 1, 11, 14, 0)) 
(datetime.datetime(2016, 1, 12, 14, 0), datetime.datetime(2016, 1, 12, 14, 0)) 
(datetime.datetime(2016, 1, 13, 14, 0), datetime.datetime(2016, 1, 13, 14, 0)) 
(datetime.datetime(2016, 1, 13, 22, 0), datetime.datetime(2016, 1, 13, 22, 0)) 
(datetime.datetime(2016, 1, 14, 14, 0), datetime.datetime(2016, 1, 14, 14, 0)) 
(datetime.datetime(2016, 1, 14, 22, 0), datetime.datetime(2016, 1, 14, 22, 0)) 
(datetime.datetime(2016, 1, 15, 14, 0), datetime.datetime(2016, 1, 15, 14, 0)) 
(datetime.datetime(2016, 1, 15, 22, 0), datetime.datetime(2016, 1, 15, 22, 0)) 
+0

謝謝!這正是我需要的。你是個明星! – omerk

+0

謝謝。我實際上將這些日期添加到列表中以設置每天的開始和結束時間。對我來說,下一步將排除該範圍之外的任何日期時間範圍。例如,如果我的開始時間是(14,0)並且結束時間是(22,0),那麼我將排除(9,0)到(10,0)作爲示例。 – omerk

0

編輯:給定新的信息,你仍然應該做一個循環,但根據一個布爾值並檢查重疊。

import datetime 

def merge_date_ranges(data): 

    input = data 
    result = [] 
    overlap = True # we assume there's overlap to begin with 

    while(overlap): 
     overlap = False # will remain false unless overlap is found 

     for t1, t2 in ((input[i], input[i+1]) for i in range(len(input)-1)): 
      if t1[1] >= t2[0]: 
       overlap = True # an overlap was found, so loop will continue 
       result.append((min(t1[0], t2[0]), max(t1[1], t2[1]))) 
      else: 
       result.append(t1) 

     if(overlap): 
      input = result # preparing the next round 

    return result 
+0

謝謝,但是這不是我所需要的。如果我不清楚,我很抱歉。基本上我想要的是結束一個沒有日期範圍重疊的新列表。 – omerk

+0

編輯答案以反映新信息,這對您需要什麼更有意義嗎? – mech