I have a list of tuples int * string, where int is the level and string is the name
let src = [ (0, "root"); (1, "a"); (2, "a1"); (2, "a2"); (1, "b"); (2, "b1"); (3, "b11"); (2, "b2"); ]
and i need to convert it to the next
let expectingTree = Branch("root", [ Branch("a", [ Leaf("a1"); Leaf("a2") ]); Branch("b", [ Branch("b1", [Leaf("b11")]); Leaf("b2") ]); ]);
Below is the way I did it, but could anyone consult the best way to achieve this. I am new to F #, and C # code to do the same would be shorter, so I think I'm wrong.
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, eg 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