代码之家  ›  专栏  ›  技术社区  ›  Dinosaurius

如何遍历元组字典?

  •  3
  • Dinosaurius  · 技术社区  · 8 年前

    month,day 存储在字典中 seasons

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

    我想查一下datetime的日期间隔 dt 找到并指定名称 S1 , S2 S3

    我试着这样做,但是 start end 似乎是数字而不是元组。

        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
    
    3 回复  |  直到 8 年前
        1
  •  2
  •   Anand S Kumar    8 年前

    1. 你似乎在假设你有一个元组中的元组,但实际上你有一个元组中的元组,因为当你试图创建一个元素的元组时,你需要在元素后面跟随一个 , ,否则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() 函数使用元组的元组。

        2
  •  -1
  •   Uri Simchoni    8 年前

    请尝试以下操作:

    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
    
        3
  •  -1
  •   Dror Av.    8 年前

    主要问题是,您正在解包元组,因此得到一个 int 进入 start end 。如果删除嵌套循环,则代码将按预期工作:

    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