Reputation: 253
Find an 'item/object/type' in a recursive tree type, the tree type is UNSORTED, thus binary search operation is not going to succeed.
Type Tree = T of (Name*Children)
And Children = Tree list
//findTree :Tree*Name -> Tree
My code(which doesn't work)
let rec findTree t n = List.find(fun (T(nameTree,childTree)) -> n=nameTree ) t
I've tried using recursion and auxFunctions, but it ends up being very messy with no success.
Upvotes: 0
Views: 559
Reputation: 14318
Your base type is essentially this (cleaned up missing types):
type Tree =
| Tree of (string * Tree list)
Now the tree is unsorted, so the best you can do is a linear search, recursively going down the child nodes until a match is found. In the following case, the search goes depth-first:
[<CompilationRepresentationAttribute(CompilationRepresentationFlags.ModuleSuffix)>]
module Tree =
let find p tree =
let rec findInner t =
match t with
| Tree(n, _) when p(n) -> Some(t)
| Tree(_, children) -> children |> Seq.choose (findInner)
|> Seq.tryFind (fun _ -> true)
| Tree(_, []) -> None
findInner tree
You can use List.choose
and List.tryFind
if you want, I used Seq
so it would stop early on tryFind
.
Also, this version has a predicate match on name. If you always want to use equality, you can add the name as parameter and swap p
for name
and when p(n)
to when n = name
.
Now, a little test:
let tree = Tree("A",
[Tree("B",
[Tree("C",[]);
Tree("D",
[Tree("E",[])])
]);
Tree("F",[])
])
tree |> Tree.find (fun n -> n = "B") |> printfn "%A"
tree |> Tree.find (fun n -> n = "D") |> printfn "%A"
tree |> Tree.find (fun n -> n = "E") |> printfn "%A"
tree |> Tree.find (fun n -> n = "TEST") |> printfn "%A"
tree |> Tree.find (fun n -> n = "F") |> printfn "%A"
Which prints, respectively:
Some (Tree ("B", [Tree ("C", []); Tree ("D", [Tree ("E", [])])]))
Some (Tree ("D", [Tree ("E", [])]))
Some (Tree ("E", []))
<null>
Some (Tree ("F", []))
Upvotes: 4