我想在树中搜索并替换,搜索子树并将其替换为另一个子树:
type Tree =
| A of string
| B of int
| C of List<Tree>
let rec replace search repl subject =
if subject = search then
repl
else
match subject with
| C l -> C (l |> List.map (replace search repl))
| _ -> subject
是否有更简单的方法或更通用的方法来执行此操作和类似的转换(例如包含)?它似乎非常适合fmap(Haskell),但我不能使它工作。
答案 0 :(得分:2)
这个功能看起来很可读。它可以缩短为:
let rec replace search repl = function
| x when x = search -> repl
| C l -> List.map (replace search repl) l |> C
| x -> x
与contains
非常相似。
为了提高通用性,您可以尝试检查树数据结构和树内容的区分联合是否可以是单独的类型,从而允许将数据键入为MyTree<MyContent>
。这可能适用于也可能不适用于该问题,但在其中,分割容器和内容会大大增加可重用性和可读性。
对于通用MyTree<'T> = Leaf of 'T | Branch of MyTree<'T> list
,检查节点(分支或叶子)的时间不会太长:
let rec containsNode node = function
| Leaf _ as x -> x = node
| Branch l as b -> b = node || List.exists (containsNode node) l
也不是替换任何节点的功能:
let rec replaceNode node newNode = function
| x when x = node -> newNode
| Branch l -> List.map (replaceNode node newNode) l |> Branch
| Leaf _ as x -> x
换句话说,简约类型和模式匹配对于此类问题可能很好。 虽然他们并非总是如此。如果不适用,请不要介意这篇文章。