【问题标题】:Iterate over subrange of weekdays迭代工作日的子范围
【发布时间】:2014-06-01 23:26:08
【问题描述】:

我正在尝试遍历一系列工作日,其中每个工作日映射到整数 (Sunday = 1, Monday = 2, ..., Saturday = 7)

范围由start and end day 定义。这对于像Monday(2) - Thursday(5) 这样的开始和结束日来说很好,我可以这样做:

for(int i = startDay; i <= endDay; i++) { ... } 

当范围在一周的结束和开始时,我遇到了困难,例如Friday(6) - Monday(2)。这显然不适用于上述 for 循环 - 例如

for(int i = 6; i <= 2; i++) { ... }    // wouldn't even execute once. 

我能看到的唯一解决方案是实现某种循环缓冲区,对于这样一个简单的问题,我觉得这太过分了。我只是被难住了,很可能在这里遗漏了一些明显的东西。我认为解决方案可能与模运算有关,但我不太确定。

【问题讨论】:

    标签: java dayofweek weekday


    【解决方案1】:

    你可以这样做:

    int numberOfDays = endDay >= startDay ? endDay - startDay : 8 - (startDay - endDay);
    for (int i = startDay; i <= startDay + numberOfDays; i++) {
        int day = (i - 1) % 7 + 1;
    }
    

    这利用了% 模运算符来确保所有值都保持在 1 - 7 之间。

    例如,一旦i 变为 8,计算将把 day 换回 1:(8 - 1) % 7 + 1 == 1

    【讨论】:

    • 给定一个像startDay = 6 and endDay = 3 这样的范围,这难道还不能执行吗? startDay + (endDay - startDay) = 6 + (3 - 6) = 3 导致:for(int i = 6; i &lt;= 3; i++) { ... } 哪个不会执行?
    • 应该是... 7 - (startDay - endDay); 而不是... 8 - (startDay - endDay);?否则总是会多加一天。
    • 这取决于你想要什么以及最后一天是否包含在范围内。
    【解决方案2】:

    使用break 可能是最清楚的,那么您不必担心所有不同的情况:

    for (int day = startDay; ; day = (day - 1) % 7 + 1) {
        // ... do your stuff
        if (day == endDay) {
            break;
        }
    }
    

    或者,有些人可能更喜欢这个:

    int day = startDay;
    while (true) {
        // ... do something
        if (day == endDay) {
            break;
        }
        day = (day - 1) % 7 + 1;
    }
    

    或:

    int day = startDay;
    while (true) {
        // ... do something
        if (day == endDay) {
            break;
        }
        if (++day > 7) {
            day = 1;
        }
    }
    

    尝试使用for 循环来正确处理所有不同的情况可能会令人头疼。你必须确保这些都得到处理:

    startDay == 1, endDay == 7
    endDay == startDay
    endDay == startDay - 1  (which should go through every day of the week in some order)
    endDay > startDay
    endDay < startDay
    

    【讨论】:

      【解决方案3】:

      在 Java 8 中:

      // input section
      DayOfWeek start = DayOfWeek.FRIDAY;
      DayOfWeek end = DayOfWeek.MONDAY;
      
      // execution section
      DayOfWeek dow = start;
      DayOfWeek stop = end.plus(1);
      
      do {
        // ... your code
        dow = dow.plus(1);
      } while (dow != stop);
      

      do-while-construction 确保对于条件start == end,循环将至少执行一次。

      因使用本地化索引而更新(星期日 = 1 而不是 7)

      您可以通过这种方式将索引转换为DayOfWeek-objects:

      private static DayOfWeek convert(int localIndex) {
        int iso = localIndex - 1;
        if (iso == 0) {
          iso = 7;
        }
        return DayOfWeek.of(iso);
      }
      

      【讨论】:

        【解决方案4】:

        您可以使用 % 运算符来实现某种循环

         for (int i=6; i!=2; i=(i+1)%7) { ... }
        

        这将从 0 开始索引天数,因此星期日 = 0 ... 星期六 = 6。如果您真的希望索引从 1 开始,那只是解释问题。例如,您可以这样做:

         for (int i=6; i!=2; i=(i+1)%7) { 
             int day=i+1; 
             // use day here
         }
        

        【讨论】:

        • 如何更改为不从 0 开始索引天数?即给定startDay = 6 and endDay = 3,我只想看看6, 7, 1, 2, 3。不是day 0
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-03-20
        • 1970-01-01
        • 2019-10-07
        • 1970-01-01
        • 2010-11-02
        • 2010-11-13
        • 2017-03-20
        相关资源
        最近更新 更多