I have nested sets data from my db and need transform this to tree data structure:
type Item = {
Id: int
Left: int
Right: int
Level: int
}
type Items = Item list
type Tree = {Parent: Item; Childrens: Tree list}
My my failed attempt:
- Get childrens items for root item and create root of tree
- Search childrens for each child from step 1, build new tree
- Repeat step 2 until transform all items (nested sets) to tree
let predicate p c = (c.Level = p.Level + 1) && (c.Left > p.Left) && (c.Right < p.Right)
let initLeaf item = {Parent = item; Childrens = []}
let initLeafs = List.map (fun x -> initLeaf x)
let getChildrens parent = List.filter (fun x -> predicate parent x)
let build (initList: Item list) =
let sortedList = initList |> List.sortBy (fun x -> x.Left)
let getChildrens2 parent =
let items = sortedList |> getChildrens parent
if not (List.isEmpty items) then items |> initLeafs else []
let root = initLeaf sortedList.Head
let rec loop (tree: Tree) =
let childrens =
match tree.Childrens with
| [] ->
getChildrens2 tree.Parent
| x ->
x |> List.collect (fun y -> loop y)
loop {tree with Childrens = childrens}
loop root
let res = build items
Here's my attempt at this. The example is taken from Wikipedia. I changed the type of
Item.Idtostringfor better output readability, but the method is still applicable.Output (truncated):
Edit: this is the shortest tail-recursive version I could come up with.
Maybe it could be improved using the continuation-passing style.