2017-08-08 128 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

你当然是对的,我可能误解了关于迭代的问题,而不是关于日期算法。 –