所以这是我从另一种语言(Lisp)翻译的函数,大部分是逐字的。但是,对我来说,这并不是很合适,使用ref
,if
没有else
等等,你会如何重写下面的第二个函数?
let directEdges node edges =
List.filter (fun (a, b) -> a = node) edges
let getConnected node edges =
let visited = ref Set.empty
let rec traverse node =
if not (Set.contains node !visited) then
visited := Set.add node !visited
directEdges node edges
|> List.iter (fun (a, b) -> traverse b)
traverse node
!visited
编辑:也没有要求代码甚至使用Set;原来只是使用了一个清单。
答案 0 :(得分:3)
总的来说,我认为你的解决方案看起来非常好 - 我认为这是一种问题,其中一些可变性使得算法的表达更清晰。但是,不是使用对重复更新的不可变集的可变引用,而是使用可变集实现可能更好:
open System.Collections.Generic
let getConnected node edges =
let visited = HashSet()
let rec traverse node =
if not (visited.Contains node) then
visited.Add node
directEdges node edges
|> List.iter (fun (a,b) -> traverse b)
traverse node
visited
如果您希望输出为不可变集,则可以在最后一行之后添加|> set
。
另一方面,如果你想使用功能方法,那就不太难了:
let getConnected node edges =
let rec traverse node visited =
if not (Set.contains node visited) then
directEdges node edges
|> List.fold (fun nodes (a, b) -> traverse b nodes) (Set.add node visited)
else
visited
traverse node Set.empty