2011-11-26 93 views
4

有日期的两个列表(没有假设,可以进行关于列表的顺序)如何合并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) 

回答

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) 
    ] 

^h ERE是一个例子:

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

+0

您可以直接生成使用方名单DateTime是否顺序括号而不是seq {}。 – gradbot

+0

@gradbot - 谢谢,我通过你的建议 –

+0

+1,而你的代码比李的更复杂,它的速度更快。你的是n log m + m log n + n log n + m log m而Lee's是(n + m)log m +(n + m)log n。 – gradbot

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)) 

注意这个返回一组,但你可以使用List.ofSeq创建一个列表,如果需要

+0

+1,简单和n日志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)] 

更新:合并功能进行了简化,使类似其他答案结果