2017-08-08 143 views
3

我有存儲在詞典seasonsmonth,day下列元組:如何遍歷元組字典?

seasons = { 
    'S1': (
     ((1, 10),(5, 31)) 
    ), 
    'S2': (
     ((9, 1),(1, 9)) 
    ), 
    'S3': (
     ((6, 1),(9, 30)) 
    ) 
} 

我想在一個日期時間dt位於該日期時間間隔檢查和分配名稱S1S2S3,相應。

我試過這樣做,但startend似乎是數字而不是元組。

def getSeason(dt): 
     season = None  
     for t, ranges in seasons.items(): 
      for start, end in ranges: 
       if date(dt.year,start(0),start(1)) <= dt.date() <= date(dt.year,end(0),end(1)): 
        season = t 
        break 
      if season is not None: 
       break 
     return season 
+1

日期是毫無意義的,而不年。你應該存儲這些年。 –

+2

@StevenRumbalski,OP只是檢查給定日期是否在一個季節(秋季,春季等)。沒有需要的一年。 如果OP包含年份,那麼使用datetime.date將是一個好主意。 – RagingRoosevelt

+0

@StevenRumbalski:我知道如何處理日期。在我的情況下,我需要(月,日)對沒有幾年。韋爾,我知道我應該解決的任務...... – Dinosaurius

回答

2

很少有什麼問題,我看到你的代碼 -

  1. 你似乎是假設你有元組的元組的元組,但你確實有TUPE的元組,因爲當你嘗試爲了製作一個元素的元組,你需要按照元素,,否則python會將它解釋爲用於分組的括號。示例 -

    a = ((1,2),) 
    

    在簡單的情況下,

    a = (1,) 
    
  2. 其次,訪問一個元組值的時候,你應該使用start[0],不start(0),因爲後者試圖調用它的功能,具有0作爲參數。

  3. 你的邏輯不考慮季節開始在一年的情況,而季節結束在下一年。

所以賽季會是什麼樣子 -

seasons = { 
    'S1': (
     ((1, 10),(5, 31)), 
    ), 
    'S2': (
     ((9, 1),(1, 9)), 
    ), 
    'S3': (
     ((6, 1),(9, 30)), 
    ) 
} 

一個小小的改變你原來的getSeason()功能,讓你的情況下工作 -

def getSeason(dt): 
    season = None  
    for t, ranges in seasons.items(): 
     for start, end in ranges: 
      if start[0] <= end[0] or (start[0] == end[0] and start[1] <= end[1]): 
       if date(dt.year,start[0],start[1]) <= dt.date() <= date(dt.year,end[0],end[1]): 
        season = t 
        break 
      else: 
       if (date(dt.year,start[0],start[1]) <= dt.date() <= date(dt.year+1,end[0],end[1])) or (date(dt.year-1,start[0],start[1]) <= dt.date() <= date(dt.year,end[0],end[1])): 
        season = t 
        break 
     if season is not None: 
      break 
    return season 

以上的工作,但你不爲你的用例確實不需要元組元組元組的元組元組,你可以將getSeasons()函數中的邏輯改爲使用元組元組。

-1

主要的問題是,你打開元組,因此得到intstartend。如果刪除了嵌套循環代碼將作爲你希望:

from datetime import datetime 

seasons = { 
    'S1': (
     (1, 10), (5, 31), 
    ), 
    'S2': (
     (9, 1), (1, 9), 
    ), 
    'S3': (
     (6, 1), (9, 30), 
    ) 
} 


def getSeason(dt): 
    for t, (start, end) in seasons.iteritems(): 
     if start[0] < end[0] and datetime(dt.year, start[0], start[1]) <= dt <= datetime(dt.year, end[0], end[1]): 
      return t 

     elif (start[0] > end[0] and 
        (datetime(dt.year, start[0], start[1]) <= dt <= datetime(dt.year + 1, end[0], end[1]) or 
        datetime(dt.year - 1, start[0], start[1]) <= dt <= datetime(dt.year, end[0], end[1]))): 
      return t 

     else: 
      continue 

    return None 
+0

錯誤:'getSeason(datetime.datetime(2017,12,31))'和'getSeason(datetime.datetime(2017,1,1))'每個返回'None'。含糊不清:當getSeason(datetime.datetime(2017,9,1))返回''S3'時,它很可能返回'S2'。 –

+0

@StevenRumbalski這個錯誤出現在季節的字典定義中,因爲它們有重疊的值,並且並不涵蓋一年中的所有日子。我添加了更正確的詞典以避免原始輸入問題。 – droravr

+0

一個賽季可能跨越一年的邊界是合理的。我認爲不應該被定義。 –

-1

嘗試以下操作:

from datetime import date 

seasons = { 
    'S1': (
     ((1, 10),(5, 31)) 
    ), 
    'S2': (
     ((9, 1),(1, 9)) 
    ), 
    'S3': (
     ((6, 1),(9, 30)) 
    ) 
} 

def getSeason(dt): 
    for sname, duration in seasons.items(): 
     start, end = duration 
     start_date = date(dt.year, start[0], start[1]) 
     end_date = date(dt.year, end[0], end[1]) 
     if dt < start_date: 
      start_date = date(start_date.year - 1, start_date.month, start_date.day) 
      end_date = date(end_date.year - 1, end_date.month, end_date.day) 
     if end_date < start_date: 
      end_date = date(end_date.year+1, end_date.month, end_date.day) 
     if start_date <= dt <= end_date: 
      return sname 
    return None 

if __name__ == '__main__': 
    s = getSeason(date(1921, 5, 24)) 
    print s 
+0

錯誤:'getSeason(date(1921,12,31))'和 'getSeason(date(1921,1,1))'每個返回'None'。 –

+0

你當然是對的,我可能誤解了關於迭代的問題,而不是關於日期算法。 –