Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/svg/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
F# 顺序-以后年份中的同一日期_F#_Sequence - Fatal编程技术网

F# 顺序-以后年份中的同一日期

F# 顺序-以后年份中的同一日期,f#,sequence,F#,Sequence,我想创建一个序列,当一周中的某一天与函数参数中的日期相同时,该序列将返回所有年份的结果 (例如:自开始日期起,2月12日为星期日的所有年份) 希望你明白我的意思。这个怎么样: let myDate (dw:System.DayOfWeek) (start:System.DateTime) = Seq.initInfinite ((+)1) // from 1..∞ |> Seq.map start.AddYears |> Seq.takeWhile (fun

我想创建一个序列,当一周中的某一天与函数参数中的日期相同时,该序列将返回所有年份的结果 (例如:自开始日期起,2月12日为星期日的所有年份)

希望你明白我的意思。

这个怎么样:

let myDate (dw:System.DayOfWeek) (start:System.DateTime) =
    Seq.initInfinite ((+)1) // from 1..∞
    |> Seq.map start.AddYears
    |> Seq.takeWhile (fun x -> x < DateTime.MaxValue)
    |> Seq.filter (fun x -> x.DayOfWeek = dw)
    |> Seq.map (fun x -> x.Year)

myDate System.DayOfWeek.Monday (new DateTime(2001,1,1)) |> Dump

Stuart的回答很好,但我忍不住想“呃,我应该删除一些代码。”你知道,从一个不确定的年份序列开始,以特定的月份/天为单位,让打电话的人决定有多少个需要使用或添加他们自己的过滤器

在这一点上,你应该考虑“傻瓜的差事”:)我遇到的第一个问题——因为我的第二个微弱测试失败了——是你不能永远快乐地继续递增
日期时间,所以你必须编写代码来限制它

因此,由于处理真实数据的变幻莫测,我最终得到了更多而不是更少的代码:

// All instances of this specified month/day beginning with 'start'.
let myDate (dw:System.DayOfWeek) (start:System.DateTime) =
    // Start with a sequence of one date for each year...
    seq {
        // Don't run the date past DateTime.MaxValue, there lurks an
        // ArgumentOutOfRangeException. Comparison also must be on the
        // valid side of DateTime.MaxValue. Don't bother with try/with
        // here in a sequence expression, you can't do that.
        let maxDateBarrier = DateTime.MaxValue.AddYears(-1)
        let mutable keepGoing, date = true, start

        while keepGoing do
            yield date

            // if date.Year % 100 = 0 then printfn "%A" date.Year

            if date <= maxDateBarrier then
                date <- date.AddYears(1)
            else
                keepGoing <- false
    }
    |> Seq.where (fun date -> date.DayOfWeek = dw)
测试#2实际上迭代了我序列中的所有日期:

// Take up to 5 before 2040.
// Note: this statement actually iterates through *all* the years in the
// sequence if you truncate to a length longer than Seq.where returns.
myDate DayOfWeek.Sunday (DateTime(2017, 2, 13))
    |> Seq.where (fun date -> date.Year < 2040)
    |> Seq.truncate 5
    |> printDates

好多了。我没有达到“减少代码”的目标,但我同意:)

我懒得编写代码,但我会这样做,以找到一种考虑闰年的有效快速算法。我认为这是一项有趣的任务,将速度与其他答案进行比较会很有趣

有14种可能的日历。如果你在谷歌上搜索这些日历,你会很快发现它们是如何重复的。我找到了这个

“公历以28年为一个周期重复。特定非闰年的日历在11年后重复两次,在6年后重复一次。闰年的日历每28年重复一次。”

我想,一年中某一天是如何重复的,可能会稍微复杂一些,但如果是这样的话,就不会太复杂了

当然,七个非闰年日历中的任何一个都将与1月至2月的一个闰年日历相匹配,当然2月29日除外。乍一看似乎很明显,从3月起也会有一场比赛,只是与1月、2月28日相比会有一天和一个日历的偏差。需要检查。我想知道这是否会影响算法,如果会,如何影响

如果您的输入是2月29日,那么显然只需要考虑闰年

因此,编写一个算法应该非常简单


希望这有点道理。我不确定每400年会发生什么,或者是否会出现其他问题。但是,很容易通过所有合理的日期进行测试,并在需要时进行调整。

我们确实理解您的意思,但您尝试过什么,您发现有什么棘手之处?这不是一个代码编写服务…
(id>(+)1)
是一种有趣的说法
(+)1)
;-]哦,是的,我把这归咎于缺少咖啡:-请注意,闰年是一个你将不得不处理的极端情况。在2012年2月29日(星期三)调用
AddYears(6)
将产生2018年2月28日(也将是星期三)。因此,除非您还通过
AddYears(i)
调用检查日历日期是否未更改,否则使用这种方法会出现误报。有关如何处理2月29日的详细信息,请参阅。您是对的,我将稍后再讨论这个问题并解决闰年问题。这是更多的代码(不是减少代码应该是目标),并增加了可变性。但是看到其他答案总是很好的=)我认为“更少的代码”应该是目标,因为这通常有助于可读性。(当然,如果较短的代码是Perl一行程序一样的乱七八糟的话,这就不适用了。)Antoine de Saint Exupéry曾经说过,“完美是实现的,不是当没有什么可添加的时候,而是当没有什么可带走的时候。”他完全正确。通常,当您将设计(或代码)精简到基本要素时,结果会更优雅、更易于阅读。因此,我通常努力将“更少的代码”作为经验法则的设计目标。@Stuart是的,我想我已经清楚地表明我“没有达到‘更少的代码’的目标”。:)我感兴趣的是出现的边界情况、终止的未终止序列以及序列操作的误用。请注意,我对闰年还不够认真,那是午餐时间的沉思
// All instances of this specified month/day beginning with 'start'.
let myDate (dw:System.DayOfWeek) (start:System.DateTime) =
    // Start with a sequence of one date for each year...
    seq {
        // Don't run the date past DateTime.MaxValue, there lurks an
        // ArgumentOutOfRangeException. Comparison also must be on the
        // valid side of DateTime.MaxValue. Don't bother with try/with
        // here in a sequence expression, you can't do that.
        let maxDateBarrier = DateTime.MaxValue.AddYears(-1)
        let mutable keepGoing, date = true, start

        while keepGoing do
            yield date

            // if date.Year % 100 = 0 then printfn "%A" date.Year

            if date <= maxDateBarrier then
                date <- date.AddYears(1)
            else
                keepGoing <- false
    }
    |> Seq.where (fun date -> date.DayOfWeek = dw)
let printDates (dates : DateTime seq) =
    for date in dates do
        printfn "%A" date.Year

// Take the next 5
myDate DayOfWeek.Sunday DateTime.Now
    |> Seq.take 5
    |> printDates
// Take up to 5 before 2040.
// Note: this statement actually iterates through *all* the years in the
// sequence if you truncate to a length longer than Seq.where returns.
myDate DayOfWeek.Sunday (DateTime(2017, 2, 13))
    |> Seq.where (fun date -> date.Year < 2040)
    |> Seq.truncate 5
    |> printDates
// Try again: Take up to 5 before 2040.
// Terminate the sequence early with takeWhile.
myDate DayOfWeek.Sunday (DateTime(2017, 2, 13))
    |> Seq.takeWhile (fun date -> date.Year < 2040)
    |> Seq.truncate 5
    |> printDates