如何在F#中合并两个日期列表?

4
有两个日期列表(不能假设列表顺序)
//first list
[date_a; date_b; date_c]
//second list
[date_A; date_B; date_C]

我在寻找一个能够返回以下内容作为条目列表的函数: 日期是唯一键(列表中只会出现单个日期)。
-> (date, true, true) in case both lists contained the date
-> (date, true, false) in case the first list contained the date
-> (date, false, true) in case the second list contained the date
(there will be no (date, false, false) entries)
3个回答

7
let showMembership l1 l2 = 
        let s1 = Set.ofList l1
        let s2 = Set.ofList l2
        Set.union s1 s2
            |> Set.map (fun d -> (d, Set.contains d s1, Set.contains d s2))

请注意,此处返回一个 Set,但如果需要,您可以使用 List.ofSeq 创建列表。

4

使用一些简单的集合操作:

open System

//'a list -> 'a list -> ('a * bool * bool) list when 'a : comparison
let merge dtl1 dtl2 =
    let dts1 = Set.ofList dtl1
    let dts2 = Set.ofList dtl2

    let dts1Only = dts1 - dts2
    let dts2Only = dts2 - dts1 
    let dtsBoth = Set.intersect dts1 dts2

    [
        for dt in dts1Only do
            yield (dt,true,false)

        for dt in dts2Only do
            yield (dt,false,true)

        for dt in dtsBoth do
            yield (dt,true,true)
    ]

这里有一个例子:

let dtl1 = 
   [DateTime.Today.AddDays(1.)
    DateTime.Today.AddDays(2.)
    DateTime.Today.AddDays(3.)
    DateTime.Today.AddDays(4.)
    DateTime.Today.AddDays(5.)
    DateTime.Today.AddDays(6.)]

let dtl2 = 
   [DateTime.Today.AddDays(4.)
    DateTime.Today.AddDays(5.)
    DateTime.Today.AddDays(6.)
    DateTime.Today.AddDays(7.)
    DateTime.Today.AddDays(8.)
    DateTime.Today.AddDays(9.)]

merge dtl1 dtl2

enter image description here


你可以直接使用方括号而不是seq {}来生成列表。 - gradbot
+1,虽然你的代码比李的更复杂,但速度更快。 你的是n log m + m log n + n log n + m log m,而李的是(n + m)log m +(n + m)log n。 - gradbot

0

使用递归函数实现的另一个示例(可能不像其他示例那样简单和快速,但采用了不同的方法):

let rec find (b: 'T list) (a: 'T) : bool * 'T list =

    match b with
    | [] -> false, b
    | h :: t ->
        if h = a then
            true, t
        else 
            let res, restB = a |> find t
            res, h :: restB  

let rec merge (a: 'T list) (b: 'T list) (order: bool) : ('T * bool * bool) list = 
    match a with
    | [] -> 
        if not(order) then
            []
        else 
            merge b a false 
    | h :: t ->
        let resA, newB = h |> find b
        (h, resA || order, resA || not(order)) :: merge t newB order 

let Merge (a: 'T list) (b: 'T list) : ('T * bool * bool) list =
    merge a b true 

而对于:

let dtl1 = 
   [DateTime.Today.AddDays(1.)
   DateTime.Today.AddDays(2.)
   DateTime.Today.AddDays(3.)
   DateTime.Today.AddDays(4.)
   DateTime.Today.AddDays(5.)
   DateTime.Today.AddDays(6.)]

let dtl2 = 
   [DateTime.Today.AddDays(4.)
   DateTime.Today.AddDays(5.)
   DateTime.Today.AddDays(6.)
   DateTime.Today.AddDays(7.)
   DateTime.Today.AddDays(8.)
   DateTime.Today.AddDays(9.)]

Merge dtl1 dtl2 

给出:

[(27.11.2011 0:00:00, true, false); (28.11.2011 0:00:00, true, false);
 (29.11.2011 0:00:00, true, false); (30.11.2011 0:00:00, true, true);
 (01.12.2011 0:00:00, true, true); (02.12.2011 0:00:00, true, true);
 (03.12.2011 0:00:00, false, true); (04.12.2011 0:00:00, false, true);
 (05.12.2011 0:00:00, false, true)]

更新:合并函数已简化,以使结果中的日期时间顺序与其他答案类似。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接