2012-08-24 61 views
3

我有開始日期列表和結束日期列表。他們被分類...如何將兩個日期列表合併爲一系列日期間隔?

start_dates = [ 
    datetime.date(2009, 11, 5), datetime.date(2009, 11, 13), 
    datetime.date(2009, 11, 25), datetime.date(2009, 11, 26), 
    datetime.date(2009, 12, 4), datetime.date(2009, 12, 7), 
    datetime.date(2009, 12, 29), datetime.date(2009, 12, 30)] 

end_dates = [ 
    datetime.date(2009, 10, 1), datetime.date(2009, 10, 2), 
    datetime.date(2009, 10, 9), datetime.date(2009, 10, 12), 
    datetime.date(2009, 11, 4), datetime.date(2009, 12, 14), 
    datetime.date(2009, 12, 15)] 

我們想要一個時間段序列,它使用start_date開始一個句點,一個end_date結束句點。時間段不能重疊:每個週期必須在下一個開始之前結束,也不能從最後一個結束的那一天開始。如果最後有一個start_date沒有合適的end_date匹配,則使用None作爲最終結束日期。

因此,輸入上面的生成:

result = (
    (datetime.date(2009, 11, 5), datetime.date(2009, 12, 14)), 
    (datetime.date(2009, 12, 29), None) 
) 

我使用for循環中的for循環,不知道如果沒有更好的辦法。性能很受關注,因爲它將應用於40年的數千場景;一些列表涉及數千個日期。

X ----

說實話,我很驚訝的人有這麼多的麻煩了解的問題......我會揭示應用再試一次,也許抽象使其難以可視化...

開始日期表示我們收到建議購買股票的日期。結束日期是我們收到賣出建議的日期。建議的來源不同,我們正在測試如果我們使用來自一個來源的購買建議,但來自另一來源的推薦建議會發生什麼。因此,我們有兩個日期序列,我們想要將這些日期序列分解成兩個或兩個以上的時間間隔,我們可以在這些日期中對股票持倉。

因此,我們從start_dates購買股票的日期。所以在11月5日我們買入一個頭寸。現在我們通過end_dates工作尋找什麼時候我們會首先被告知出售它 - 12月14日。現在重複等待買入建議,然後是賣出建議。因此,您可以交替列表以獲得日期對的邏輯序列。如果最後我們持有一個未平倉頭寸,我們注意到通過使用None或提供一個特殊日期關閉。

+1

結果如何達到您想要達到的效果。它很難說只是從這個問題你怎麼想這將變成 –

+0

@PabloKarlsson我相信所期望的結果已經在問題中指定?!這是一個日期元組列表。 –

+0

是的,但我如何映射它們(start_dates [1],end_dates [1])? –

回答

1

我終於揭穿了它歸結爲:

trades = [] 
    enddate = datetime.date(1900, 1, 1) 
    try: 
     for startdate in startdates: 
      if enddate <= startdate: 
       enddate = enddates.next() 
       while enddate <= startdate: 
        enddate = enddates.next() 
       trades.append((startdate, enddate)) 
    except StopIteration: 
     trades.append((startdate, None)) 

感謝那些誰問的問題和回答。因爲沒有理性的原因,這個小小的謎題對我來說成了一個固定的東西,但我終於認爲我已經完成了這件事,並且應該繼續我的生活。這真的非常簡單 - 驚人的多少工作才能使它變得如此簡單!

0

這個怎麼樣。

all_dates = start_dates.expand(end_dates) 
all_dates.sort() 

look_for_start = 1; 
date = [] 
start_date = None 
end_date = None 
for i in range(len(all_dates)): 
    if look_for_start and all_dates[i] in start_dates: 
    start_date = all_dates[i] 
    look_for_start = 0; 

    elsif !look_for_start and all_dates[i] in end_dates: 
    end_date = all_dates[1] 
    look_for_start = 1; 

    if start_date == end_date: 
    end_date == None 
    look_for_start = 0; 

    if start_date != None and end_date != None; 
    date.append((start_date,end_date)) 
    start_date = None 
    end_date = None 

在此之後,您的start_dates結束日期儘可能。只取剩餘一套start_dates的,並得到他們的結束日期設置爲無

+0

列表中沒有'expand'方法,我認爲你的意思是'extend'。而這不會產生所需的輸出。 – sberry

+0

感謝我使用衆多的語言困惑.. –

+0

雖然這仍然不會創建所需的輸出? – sberry

2

編輯

這應該與len(start_dates)+len(end_dates)規模:

def date_range(start_dates, end_dates): 
    result = [] 

    start_i = 0 
    end_i = 0 

    while start_i<len(start_dates): 
     while end_i<len(end_dates) and start_dates[start_i]>end_dates[end_i]: 
      end_i += 1 
     if end_i == len(end_dates): 
      result.append((start_dates[start_i], None)) 
      break 
     result.append((start_dates[start_i], end_dates[end_i])) 
     while start_i<len(start_dates) and start_dates[start_i]<=end_dates[end_i]: 
      start_i += 1 
     end_i += 1 

    return result 

用法:

In : start_dates = [ 
    ....:  datetime.date(2009, 11, 5), datetime.date(2009, 11, 13), 
    ....:  datetime.date(2009, 11, 25), datetime.date(2009, 11, 26), 
    ....:  datetime.date(2009, 12, 4), datetime.date(2009, 12, 7), 
    ....:  datetime.date(2009, 12, 29), datetime.date(2009, 12, 30)] 

In : end_dates = [ 
    ....:  datetime.date(2009, 10, 1), datetime.date(2009, 10, 2), 
    ....:  datetime.date(2009, 10, 9), datetime.date(2009, 10, 12), 
    ....:  datetime.date(2009, 11, 4), datetime.date(2009, 12, 14), 
    ....:  datetime.date(2009, 12, 15)] 

In : date_range(start_dates, end_dates) 
Out: 
[(datetime.date(2009, 11, 5), datetime.date(2009, 12, 14)), 
(datetime.date(2009, 12, 29), None)] 

In : start_dates = [ 
    ....:  datetime.date(2009, 11, 5), datetime.date(2009, 11, 13), 
    ....:  datetime.date(2009, 11, 25), datetime.date(2009, 11, 26), 
    ....:  datetime.date(2009, 12, 4), datetime.date(2009, 12, 7), 
    ....:  datetime.date(2009, 12, 29), datetime.date(2009, 12, 30)] 

In : end_dates = [ 
    ....:  datetime.date(2009, 10, 1), datetime.date(2009, 10, 2), 
    ....:  datetime.date(2009, 10, 9), datetime.date(2009, 10, 12), 
    ....:  datetime.date(2009, 11, 7), datetime.date(2009, 12, 14), # changed (2009, 11, 4) -> (2009, 11, 7) 
    ....:  datetime.date(2009, 12, 15)] 

In : date_range(start_dates, end_dates) 
Out: 
[(datetime.date(2009, 11, 5), datetime.date(2009, 11, 7)), 
(datetime.date(2009, 11, 13), datetime.date(2009, 12, 14)), 
(datetime.date(2009, 12, 29), None)] 
+0

不錯。儘管我仍然試圖琢磨它是如何工作的。 –

+0

我想知道,因爲我可能誤解了這個問題......如果你將結束日期從'2009-11-04'更改爲'2009-11-07',預期輸出是什麼?這個答案會導致相同的結果。 – sberry

+0

這是正確的。答案不會改變。 –

1

我想這應該工作得到日期元組,但我不能建議你的方式,而不使用循環,因爲它可能會得到莫反而變得複雜。

雖然這個邏輯非常簡單明瞭。

result = [] 
for startd in start_dates: 
    if not result or result[-1][1] is not None and startd>result[-1][1]: 
    #can use 'len(result)==0' instead of 'not result' 
     for endd in end_dates: 
      if endd>startd: 
       result.append((startd,endd)) 
       break 
     else: 
      result.append((start,None)) 
    if result[-1][1] is None: 
     break 

result = tuple(result) 
print result 
相關問題