タプルのリストint*stringがあります。ここで、intはレベル、stringは名前です。
let src = [
(0, "root");
(1, "a");
(2, "a1");
(2, "a2");
(1, "b");
(2, "b1");
(3, "b11");
(2, "b2");
]
そして私はそれを次のように変換する必要があります
let expectingTree =
Branch("root",
[
Branch("a",
[
Leaf("a1");
Leaf("a2")
]);
Branch("b",
[
Branch("b1", [Leaf("b11")]);
Leaf("b2")
]);
]);
以下は私がそれをした方法ですが、それを達成するためのより良い方法で誰かがアドバイスすることができます。私はF#を初めて使用しますが、同じことを行うC#コードは少し短くなるので、間違っていると思います。
type Node =
| Branch of (string * Node list)
| Leaf of string
let src = [
(0, "root");
(1, "a");
(2, "a1");
(2, "a2");
(1, "b");
(2, "b1");
(3, "b11");
(2, "b2");
]
let rec setParents (level:int) (parents:list<int>) (lst:list<int*int*string>) : list<int*int*string> =
//skip n items and return the rest
let rec skip n xs =
match (n, xs) with
| n, _ when n <= 0 -> xs
| _, [] -> []
| n, _::xs -> skip (n-1) xs
//get parent id for given level
let parentId (level) =
let n = List.length parents - (level + 1)
skip n parents |> List.head
//create new parent list and append new id to begin
let newParents level id =
let n = List.length parents - (level + 1)
id :: skip n parents
match lst with
| (id, l, n) :: tail ->
if l = level then (id, parentId(l), n) :: setParents l (newParents l id) tail
elif l <= level + 1 then setParents l parents lst
else [] //items should be in order, e.g. there shouldnt be item with level 5 after item with level 3
| _ -> []
let rec getTree (root:int) (lst: list<int*int*string>) =
let getChildren parent =
List.filter (fun (_, p, _) -> p = parent) lst
let rec getTreeNode (id:int) (name:string) =
let children = getChildren id
match List.length children with
| 0 -> Leaf(name)
| _ -> Branch(name,
children
|> List.map (fun (_id, _, _name) -> getTreeNode _id _name))
match getChildren root with
| (id, _, n) :: _ -> getTreeNode id n
| _ -> Leaf("")
let rec printTree (ident:string) (tree:Node) =
match tree with
| Leaf(name) ->
printfn "%s%s" ident name
| Branch(name, children) ->
printfn "%s%s" ident name
List.iter (fun (node) -> printTree (" " + ident) node) children
let tree =
src
|> List.mapi (fun i (l, n) -> (i+1, l, n)) //set unique id to each item
|> setParents 0 [0] //set parentId to each item
|> getTree 0
printTree "" tree
Console.ReadKey() |> ignore