在日期范围内寻找差距


15

给定日期范围列表r作为输入,输出或返回在中找不到的任何范围r

为了这个示例,输入将采用YYYY-MM-DD格式。

假设您有三个日期范围:

[2019-01-01, 2019-02-01]
[2019-02-02, 2019-04-05]
[2019-06-01, 2019-07-01]

您会看到2019-04-05和之间存在缝隙2019-06-01

输出将是该差距: [2019-04-06, 2019-05-31]

规则

  • 输入和输出可以采用任何合理的日期或收集格式,只要保持一致即可。
  • 假设输入未排序。
  • 您的日期范围不必为[latest, earliest],但必须遵循规则2。
  • 假设输入中没有重叠的日期

测试用例:

输入: [[2019-01-01, 2019-02-01],[2019-02-02, 2019-04-05],[2019-06-01, 2019-07-01]]

输出: [[2019-04-06, 2019-05-31]]


输入: [[2019-01-01, 2019-02-01],[2018-02-02, 2018-04-05],[2019-06-01, 2019-07-01]]

输出: [[2018-04-06, 2018-12-31], [2019-02-02, 2019-05-31]]


输入: [[2019-01-01, 2019-02-01],[2019-02-02, 2019-03-02],[2019-03-03, 2019-07-01]]

输出: []


输入: [[2019-01-01, 2019-02-01], [2019-11-02, 2019-11-20]]

输出: [[2019-02-02, 2019-11-01]]


输入: [[2019-01-01, 2019-02-01],[2019-02-03, 2019-04-05]]

输出:[[2019-02-02, 2019-02-02]][[2019-02-02]]


5
我建议将所有示例日期都重新制作为ISO格式,YYYY-MM-DD因为当前格式对于许多人来说都是陌生的,并且由于使用小于等于12的月份,因此更难以解析。
亚当

@Adám好主意,已更新。
奥利弗

我们可以将输入作为.NET OLE自动化日期吗?
亚当

@Adám是的。任何合理的日期格式都是可以接受的。
奥利弗

1
是否可以订购日期?另外,在两个日期之内,后一个会是最后一个吗?
无知的体现,

Answers:


4

APL(Dyalog扩展)28 25 24字节

匿名默认前缀功能。参数和结果是自一个纪元以来的两列天数矩阵,每一行代表一个范围。

1 ¯1+⍤1∘{⍵⌿⍨1<-⍨/⍵}1⌽⍢,∧

在线尝试!In从对3元素列表(在ISO订单日期)的清单预处理器函数转换到的IDN 2列的矩阵,国际日号(1899年12月31日以来天)。在Out从的IDN至3元素列表的矩阵的矩阵后处理器功能转换。

 升序排序

1⌽
⍢, 松散(展平)时, 将日期左移一次,将其循环旋转一次–之后,重新整形为原始形状

1 ¯1+ 添加一个和负一
⍤1 使用该列表对每一行
 的结果
{... } 下面拉姆达:
 参数
-⍨/ 减法左手从右手日期,逐行日期
1< 掩模,其中差值超过一个(即,其中范围是不相邻的)
⍵⌿⍨ 过滤器那个面具旁边的行


3

C#(Visual C#交互式编译器),108字节

n=>{n.Sort();for(int i=0;;)Write(n[i].b.AddDays(1)==n[++i].a?"":n[i-1].b.AddDays(1)+""+n[i].a.AddDays(-1));}

通过以格式打印输出DD/MM/YYYY 12:00:00 AMDD/MM/YYYY 12:00:00 AM。将导致IndexOutOfRange异常,这对于每个元共识都可以。

在线尝试!

如果我们以unix纪元以来的天数作为输入,我们可以将其简化为...

83个字节

n=>{n.Sort();for(int i=0;;)Print(n[i].b+1==n[++i].a?"":n[i-1].b+1+" "+(n[i].a-1));}

在线尝试!

我们可以用/u:System.Array旗帜进一步打高尔夫,因为...

78字节

n=>{Sort(n);for(int i=0;;)Print(++n[i].b==n[++i].a--?"":n[i-1].b+" "+n[i].a);}

在线尝试!





2

PHP,208个197 190 177字节

笨拙的笨拙坐在墙上...尽管新方法具有一定的打高尔夫球潜力。

function($a){sort($a);for($m=$x=$a[0][0];$f=$m<=$x;$f^$g&&print($g=$f)?"$m/":"$n
",$m=date("Y-m-d",strtotime($n=$m)+9e4))foreach($a as$d)$x=max($x,$d[1|$f&=$m<$d[0]|$m>$d[1]]);}

函数以ISO格式获取[开始,结束]范围的数组,并打印间隔。在线尝试


分解

function($a){
    sort($a);                           # sort ranges (for easy access to min date)
    for($m=$x=$a[0][0];$f=$m<=$x;       # loop from min date to max date, 1. set flag
        $f^$g&&print($g=$f)?"$m/":"$n\n",       # 4. flag changed: backup flag, print date
        $m=date("Y-m-d",strtotime($n=$m)+9e4)   # 5. backup and increment date
    )foreach($a as$d)
        $x=max($x,$d[1                          # 2. find max date
            |$f&=$m<$d[0]|$m>$d[1]              # 3. date found in ranges: clear flag
        ]);
}

1

果冻,13 个字节

FṢṖḊs2+Ø+>/Ðḟ

果冻(当前)没有内置日期,因此它使用“ days-since-epoch”。
范围(整数对)的输入列表可以是混合顺序和混合方向。
结果是按升序排列的升序范围列表。

在线尝试!(页脚格式为将空白列表显示为[]

怎么样?

注意:这取决于保证规则中规定的“输入中没有重叠的日期”。

FṢṖḊs2+Ø+>/Ðḟ - Link: list of pairs of integers
F             - flatten
 Ṣ            - sort
  Ṗ           - pop (remove tail)
   Ḋ          - dequeue (remove head)
    s2        - split into twos
       Ø+     - literal [1,-1]
      +       - add (vectorises)
           Ðḟ - filter discard those for which:
          /   -   reduce by:
         >    -     greater than?

有趣的是,我不知道Jelly没有日期支持。这是通常的方法吗?自时代起使用了几天?
dana

我相信,自从纪元以来的几天被某些系统使用(也许是Excel)。自纪元以来的秒数更为常见(例如Unix)。尽管有些松懈,但我还是采用了似乎可以满足要求的方法。
乔纳森·艾伦,

嘘,您可以手动计算日期。; P自纪元以来的天数实际上更常用于不支持日期的语言。不过,我确实觉得这使这项挑战变得更加容易。
凯文·克鲁伊森

@KevinCruijssen嘿,同意。
乔纳森·艾伦,

1

C#(Visual C#交互式编译器),103字节

x=>{var(a,_)=x[0];foreach(var(b,c)in x.OrderBy(y=>y)){if(a<b)Print((a,b.AddDays(-1)));a=c.AddDays(1);}}

在线尝试!

输入是开始/结束日期元组的列表。将每个缺少的范围输出到STDOUT。

// x: input list of start/end date tuples
x=>{
  // variable definitions...
  // a: 1 day after the end date of the previous range
  // b: start of the current range
  // c: end of the current range

  // start by deconstructing the start date of the first tuple
  // into a. a will then be a DateTime and will contain a value
  // at least a large as the smallest start date.
  var(a,_)=x[0];
  // iterate over sorted ranges
  foreach(var(b,c)in x.OrderBy(y=>y)){
    // if the day after the end of the previous range is less
    // than the start of the current range, then print the
    // missing days.
    if(a<b)
      Print((a,b.AddDays(-1)));
    // save the day after the current range to a for next iteration
    a=c.AddDays(1);
  }
}


哈-如果您确实像“无知的体现”那样打印,您会变得很小- 在线尝试!
dana

真好 还要为后两个输入法输入它们的输入法
仅ASCII,

好吧,实际上...这看起来确实不正确
ASCII码仅

1
是的,现在看起来不错
仅使用ASCII

1

R,88字节

function(a,b=a[order(a$x),],d=c(b$x[-1]-b$y[-nrow(b)],0))data.frame(b$y+1,b$y+d-1)[d>1,]

在线尝试!

这将日期范围的数据框作为输入,并输出缺少范围的数据框。我相当确定这可以解决更多问题,但是我遇到了与的问题ccbind而其他人则取消了日期类。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.