通过元组成员

时间:2016-09-08 17:12:36

标签: f#

假设我有一个decimal*decimal

列表
let tup = [(1M, 2M); (2M, 3M); (3M, 3M); (4M, 5M); (5M, 6M); (7M, 6M); (8M, 9M); (10M, 9M)]

如果可以连接所有值,我需要一个可以将所有值组合在一起的函数,例如

map[(100, [1M; 2M; 3M]); (101, [4M; 5M; 6M; 7M]); (102, [8M; 9M; 10M])]

我不能只做一个List.groupBy,因为这会错过任何其他可能连接起来的"线下"通过另一个十进制值。地图中的int值是任意的。我希望能够种子"然后,起始值逐渐增加一些值。

该功能看起来能做什么?

3 个答案:

答案 0 :(得分:3)

我是对的,通过'连接'你的意思是数字代表节点而元组代表无向图中的边?据我所知,标准库中没有功能可以做到这一点。您可以搜索执行基本图形操作的某个库。您要执行的操作是划分为connected components

您也可以尝试从头开始实现该功能。 这是一些nice attempt

答案 1 :(得分:2)

您尝试完成的似乎已经得到充分解决;关于如何完成它,这是一种方法:

let groupConnected initId idTups =
    let mergeGroups projectIds input =
        (List.empty<SortedSet<_>>, input)
        ||> List.fold (fun groups x ->
            let ids = projectIds x
            match groups |> List.tryFind (fun g -> g.Overlaps ids) with
              | Some g -> g.UnionWith ids
                          groups
              | _      -> ids::groups)
    idTups
    |> mergeGroups (fun (a, b) -> SortedSet([| a; b |]))
    |> mergeGroups id
    |> List.sortBy (fun g -> g.Min)
    |> Seq.mapi (fun i g -> initId + i, List.ofSeq g)
    |> Map.ofSeq

使用此问题和后续问题的输入进行测试:

> groupConnected 100 [(1M, 2M); (2M, 3M); (3M, 3M); (4M, 5M); (5M, 6M); (7M, 6M);
                      (8M, 9M); (10M, 9M)];;
val it : Map<int,decimal list> =
  map [(100, [1M; 2M; 3M]); (101, [4M; 5M; 6M; 7M]); (102, [8M; 9M; 10M])]


> groupConnected 100 [(1M, 1M); (2M, 18M); (3M, 3M); (4M, 5M); (5M, 24M); (24M, 6M);
                      (7M, 6M); (8M, 9M); (10M, 9M)];;
val it : Map<int,decimal list> =
  map
    [(100, [1M]); (101, [2M; 18M]); (102, [3M]); (103, [4M; 5M; 6M; 7M; 24M]);
     (104, [8M; 9M; 10M])]

Online Demo

答案 2 :(得分:1)

这是一个不太漂亮的解决方案:

let tup = [(1M, 2M); (2M, 3M); (3M, 3M); (4M, 5M); (5M, 6M); (7M, 6M); (8M, 9M); (10M, 9M)]

let findGroupings lst =
    let rec findGroup input previous acc =
        match input with
        | [] -> acc
        | (a,b)::t -> 
            match previous with
            | [] -> if a >= b then
                        findGroup t [] acc
                    else
                        findGroup t [b;a] acc
            | h::_ -> if a > h && a < b then
                        findGroup t (b::(a::previous)) acc
                      elif a > h && a >=b then
                        let full = List.rev (a::previous)
                        findGroup t [] (full::acc)
                      elif a >= b then
                        findGroup t [] ((List.rev previous)::acc)
                      elif a < h then
                        findGroup t [b;a] (previous::acc)
                      else // a = h and a < b
                        findGroup t (b::previous) acc
    findGroup lst [] []
    |> List.rev

使用

let result = findGroupings tup

给出

val result : decimal list list = [[1M; 2M; 3M]; [4M; 5M; 6M; 7M]; [8M; 9M; 10M]]