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

时间:2011-11-26 14:40:39

标签: f#

有两个日期列表(不能对列表顺序做出任何假设)

//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 个答案:

答案 0 :(得分: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创建一个列表(如果需要)

答案 1 :(得分: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

答案 2 :(得分: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)]

更新:简化了合并功能,使得DateTimes在结果中的顺序与其他答案类似