我怎样才能使这更地道?

发布于 2024-10-20 13:08:30 字数 592 浏览 1 评论 0原文

这是我从另一种语言(Lisp)翻译而来的函数,大部分是逐字翻译的。不过,我觉得不太对劲,如果使用 refif 而不使用 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;原来只是使用了一个列表。

So here is a function I translated from another language (Lisp), mostly verbatim-ish. It doesn't smell quite right to me though, what with using ref, if without else, etc. How would you rewrite the second function below?

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

Edit: There's also no requirement that the code even use a Set; the original just used a list.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

美人骨 2024-10-27 13:08:30

总的来说,我认为你的解决方案看起来相当不错 - 我认为这是一种稍微可变性使算法的表达更清晰的问题。但是,与其使用对重复更新的不可变集的可变引用,不如仅使用可变集实现:

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

如果您希望输出是不可变集,则只需添加 |> ;设置在最后一行之后。

另一方面,如果您想使用函数式方法,这并不太难:

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

Overall, I think that your solution looks pretty good - I think this is the sort of problem where a bit of mutability makes the expression of the algorithm clearer. However, rather than using a mutable reference to an immutable set which you update repeatedly, it might be better to just use a mutable set implementation:

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

and if you want the output to be an immutable set, you can just add |> set after the last line.

On the other hand, if you want to use a functional approach it's not too hard:

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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文