[英]Finding children in a tree using F#
我正在尝试使用F#为简单的树结构建模,不禁以为我做得很糟糕:
我的树本质上是叶子列表(最终将保留到数据库表中)。 我有一个函数getChildren,它接收叶子的NodeID并递归返回该叶子的所有子代。
open System.Collections.Generic
type leaf = { nodeID : int; nodeDescr : string; parentID : int option}
let myTree = [ { nodeID = 0; nodeDescr = "Root"; parentID = None };
{ nodeID = 1; nodeDescr = "Mechanical"; parentID = Some(0) } ;
{ nodeID = 2; nodeDescr = "Electrical"; parentID = Some(0) } ;
{ nodeID = 3; nodeDescr = "High Voltage"; parentID = Some(2) } ;
{ nodeID = 4; nodeDescr = "Low Voltage"; parentID = Some(2) } ;
{ nodeID = 5; nodeDescr = "HV Maintanence"; parentID = Some(3) } ;
{ nodeID = 6; nodeDescr = "City Power"; parentID = Some(3) } ;
{ nodeID = 7; nodeDescr = "LV Wiring"; parentID = Some(4) } ;
{ nodeID = 8; nodeDescr = "LV Maintanence"; parentID = Some(4) } ]
let getChildren (id : int) (tree : list<leaf>) =
let allChildren = new List<leaf>() // Mutable list
let rec getAllChildren (id : int) (t : list<leaf>) =
let cl = List.filter (fun x -> x.parentID = Some id) t // Get the immediate children
for c in cl do // Loop through the immediate children and recursively get their children
allChildren.Add(c)
getAllChildren c.nodeID t
getAllChildren id tree
allChildren
我在这里担心的是:
我怀疑在F#中使用函数式编程时,可以采用更优雅的方法来避免突变和循环,而我的命令式编程习惯正在悄悄溜走。
另外,考虑到需要从数据库表中存储和检索树结构,这是对树结构进行建模的好方法吗?
如果要保留已有的树结构,此函数将为您找到子级,而不会循环或产生可变值:
let getChildren (id : int) (tree : list<leaf>) =
let parent node = tree |> Seq.filter (fun x -> Some x.nodeID = node.parentID) |> Seq.exactlyOne
let rec hasAncestor (node : leaf) =
node.parentID = Some id || (node.parentID.IsSome && hasAncestor (parent node))
tree |> Seq.filter hasAncestor
但是,您可能真正想要的是每个节点都存储对其子节点的引用的结构,当您序列化数据时,您可以从引用中找到ID
希望这样的事情足以指引您正确的方向:
type Node = {
Id : int;
Description: string;
Children: seq<Node>
}
let myTree =
{ Id = 0; Description = "Root"; Children =
[
{ Id = 1; Description = "Mechanical"; Children = [] };
{ Id = 2; Description = "Electrical"; Children =
[
{ Id = 3; Description = "High Voltage"; Children =
[
{ Id = 5; Description = "HV Maintanence"; Children = [] };
{ Id = 6; Description = "City Power"; Children = [] }
] };
{ Id = 4; Description = "Low Voltage"; Children =
[
{ Id = 7; Description = "LV Wiring"; Children = [] } ;
{ Id = 8; Description = "LV Maintanence"; Children = [] }
] }
]};
]}
let rec getChildren (node : Node) =
Seq.concat [node.Children; (Seq.collect getChildren node.Children)]
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.