Как я могу объединить два списка дат в F #? - PullRequest
4 голосов
/ 26 ноября 2011

Существует два списка дат (никаких предположений относительно порядка списка нельзя)

//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 голосов
/ 26 ноября 2011
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 для создания списка, если требуется

4 голосов
/ 26 ноября 2011

Используя несколько простых операций над множествами:

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

0 голосов
/ 26 ноября 2011

Другой пример, реализованный с помощью рекурсивных функций (возможно, не такой простой и быстрый, как другие, но сделанный с другим подходом):

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 в результате, аналогично другим ответам

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...