将类型插入F#树

时间:2016-10-24 02:02:38

标签: f#

我设法在这里做了一大碗意大利面,无法找到出路。我试图将一个类型插入树中,然后重新排序树后的位置。

以下是我的类型:

type Government = {
    Id : Id;
    Name : string;
    Abbreviation : string;
    ParentId : string option;
}

type GovernmentStructure<'gov> = 
    | Root of Government : 'gov * SubGov : GovernmentStructure<'gov> list
    | Node of Government : 'gov * SubGov : GovernmentStructure<'gov> list
    | Leaf of Government : 'gov

这里是意大利面条lol。它没有用,但它显示了我被卷入的头脑风暴。

let insertGovernment (posGov: Government) (newGov : Government) (parentId : string)
    (currentStructure : GovernmentStructure<Government> list) =

    let rec reorderStructure (govPos : Government) (newGov : Government)
        (currentStructure : GovernmentStructure<Government>) =

        match currentStructure with
        | Root(gov', subGov) when gov' = govPos ->
            let rec updateSubGov parentId (movGov: Government) 
                (uSubGov : GovernmentStructure<Government> list) =
                [
                    Node({
                            Government.Id = movGov.Id;
                            Name = movGov.Name;
                            Abbreviation = movGov.Abbreviation;
                            ParentId = Some(parentId)
                        },[
                            for x in uSubGov do
                                match x with
                                | Node(g, s) -> yield! (updateSubGov movGov.Id g s)
                                | Leaf(g) -> yield x
                        ])
                ]


            Root(newGov, (updateSubGov newGov.Id gov' subGov)) 
        | node ->
            let rec updateStructure parentId (insGov : Government) 
                (node : GovernmentStructure<Government> list) =
                match node with
                | Root(gov', subGov) ->
                    Root(gov', [
                                for (x) in subGov do
                                    match x with
                                    | Node(g,s) when g = govPos ->  
                                        yield Node(insGov, updateStructure g.Id s )

                                    | Node(g,s) -> yield Node(g, updateStructure g.Id s)
                            ])
                | Node(gov', subGov) when gov' = govPos ->

                    [
                        Node({
                                Government.Id = insGov.Id;
                                Name = insGov.Name;
                                Abbreviation = insGov.Abbreviation;
                                ParentId = Some(parentId)
                            },[
                                for x in uSubGov do
                                    match x with
                                    | Node(g,s) -> yield Node(g, updateStructure movGov.Id g s)
                            ])
                    ]
                | Leaf(g) -> 
                    [
                        Node(newGov, [Leaf({
                                            g with ParentId = newGov.Id
                                        })])
                    ]
            node |> (fun x -> 
                            match x with
                            | Root(g,s) -> Node(g,(updateStructure g.Id g s))
                            | Node(g,s) -> Node(g,(updateStructure g.Id g s)))

帮助!!!我淹死在酱汁里,哈哈。

1 个答案:

答案 0 :(得分:0)

这是我能够提出的解决方案。我不怀疑存在更有效的答案。

let insertGovernment (posGov: Government) (newGov : Government)
(currentStructure : GovernmentStructure<Government>) =

let updateStructure (govPos : Government) (newGov : Government)
    (currentStructure : GovernmentStructure<Government>) =

    // iterate over the nodes to find position and insert. parentId is useless, will fix later 
    let rec findPosAndInsertInto parentId (startStructure : GovernmentStructure<Government>) =
        match startStructure with
        | Node (g, sg) when g = govPos ->
            Node(g, [
                            yield Node(newGov, [])
                            yield! sg
                        ])
        | Node (g, sg) ->
            Node (g, [
                        for x in sg do
                            yield findPosAndInsertInto g.Id x
                    ])
        | Leaf(g) when g = govPos -> 
            Node (g, [Leaf(newGov)])
        // better logic needed, should not hit this
        | node -> node

    match currentStructure with
    // Insert if position is at root
    | Root(gov', subGov) when gov' = govPos ->

        Root(gov', [    
                        yield Node(newGov, [])
                        yield! subGov
                    ]) 
    // Insert if position is at node or leaf
    | node -> 
        match node with
        | Root (gov', subGov) ->
            Root(gov', [
                        for x in subGov do
                            yield findPosAndInsertInto gov'.Id x 
                    ])
        // better logic needed, shouldn't hit this level
        | node -> node

updateStructure posGov newGov currentStructure