【问题标题】:Recursive algorithm for coalescing / collapsing list of dates into ranges用于将日期列表合并/折叠成范围的递归算法
【发布时间】:2011-02-20 21:27:09
【问题描述】:

给定日期列表

12/07/2010
13/07/2010
14/07/2010
15/07/2010
12/08/2010
13/08/2010
14/08/2010
15/08/2010
19/08/2010
20/08/2010
21/08/2010

我正在寻找用于生成范围列表的递归伪代码算法(我可以将其转换为 FileMaker 自定义函数)的指针,即

12/07/2010 to 15/07/2010, 12/08/2010 to 15/08/2010, 19/08/2010 to 20/08/2010

该列表已预先排序和重复数据删除。我已经尝试从第一个值和向前工作,最后一个值和向后工作开始,但我似乎无法让它工作。度过那些令人沮丧的日子......如果签名是这样的就好了

CollapseDateList( dateList, separator, ellipsis )

:-)

【问题讨论】:

    标签: pseudocode recursion collapse date-range coalesce


    【解决方案1】:

    主程序看起来像这样:

    List<String> list  = new ArrayList<String>();
    
    String firstDate   = dateList[0];
    String lastDate    = dateList[0];
    String currentDate = dateList[0];
    
    for (int i = 1; i < dateList.length(); i++) {
        if (dateDiff(dateList[i], currentDate) == 1) {
            lastDate   = dateList[i];
        } else {
            list.add(firstDate + separator + lastDate);
            firstDate = dateList[i];
            lastDate  = dateList[i];
        }
        currentDate = dateList[i];
    }
    list.add(firstDate + separator + lastDate);
    

    我假设你有一些函数可以告诉你两个日期是否连续。

    【讨论】:

    • 不确定这是如何递归的?
    • @Dycey:伪代码不是递归的,除非你考虑循环递归。
    • 这是一个耻辱,因为我要求递归代码(标题中的第一个词:-))!我并没有迟钝 - FileMaker 自定义函数使用某种函数式语言,因此您需要使用递归来代替循环。
    【解决方案2】:

    下面是执行这项工作的递归 FileMaker 代码。基本方法是在适当的位置进行替换,必要时从一个值内的最后一个日期(最右边的单词)计算日期。这样它就可以决定何时检查下一个值是否仍然是第一个范围的一部分,或者将第一个范围标记为完成并专注于其余的值。希望对其他人有所帮助。

    // CollapseDateList( dates, comma, dash)
    
    Let(
      countDates = ValueCount ( dates );
    
      If (
        countDates < 2 ; dates;  // return the dates we've been given...
    
        Let(
          [ 
            start_date = GetAsDate( LeftWords( GetValue ( dates ; 1 ); 1 ) );
            date_1 = GetAsDate( RightWords( GetValue ( dates ; 1 ); 1 ) );
            date_2 = GetAsDate( GetValue ( dates ; 2 ) );
            date_3 = GetAsDate( GetValue ( dates ; 3 ) );
            dv_1 = GetAsNumber( date_1 );
            dv_2 = GetAsNumber( date_2 );
            dv_3 = GetAsNumber( date_3 );
            twoFollowsOne = (dv_2 = dv_1 + 1);
            threeFollowsTwo = (dv_3 = dv_2 + 1)
          ];
    
           // compare dates
          Case(
            // only two dates in list
            countDates = 2;
              if (
                twoFollowsOne;
                start_date & dash & date_2;
                GetValue ( dates ; 1 ) & comma & date_2
              );
    
            // first three values are sequential
            threeFollowsTwo and twoFollowsOne; 
              CollapseDateList( start_date & dash & date_3 & ¶ & RightValues( dates; countDates - 3 ); comma; dash );
    
            // first two values are sequential only
            not threeFollowsTwo and twoFollowsOne; 
              start_date & dash & date_2 & comma & CollapseDateList(  RightValues(  dates; countDates - 2 ); comma; dash );
    
            // first two values are not sequential 
            // default
            GetValue ( dates ; 1 ) & comma & CollapseDateList( RightValues( dates; countDates - 1 ); comma; dash )
          ) 
        )
      )
    )
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-06-25
      • 2010-09-14
      • 2017-12-07
      • 1970-01-01
      • 2012-06-03
      • 2021-09-28
      • 2013-01-04
      • 1970-01-01
      相关资源
      最近更新 更多