减少递归搜索的代码行数

时间:2013-08-14 16:51:28

标签: clojure

减少我在Lisp / Clojure中编写的代码行是我的一种迷恋。我试图使下面的代码(本质上是深度优先搜索)更短。

(defn find-node  [nodeid in-node]
  (if (= nodeid (:id in-node))
    in-node
    (loop [node nil activities (:activities in-node)]
      (if (or (empty? activities) (not (nil? node)))
        node
        (recur (find-node nodeid (first activities)) (rest activities))))))

(defn find-node-in-graph [nodeid node activities]
  (if (empty? activities)
    node
    (recur nodeid (find-node nodeid (first activities)) (rest activities))))

(defrecord Graph [id name activities])
(defrecord Node [id name activities])

(defn find-node [nodeid in-node] (if (= nodeid (:id in-node)) in-node (loop [node nil activities (:activities in-node)] (if (or (empty? activities) (not (nil? node))) node (recur (find-node nodeid (first activities)) (rest activities)))))) (defn find-node-in-graph [nodeid node activities] (if (empty? activities) node (recur nodeid (find-node nodeid (first activities)) (rest activities)))) (defrecord Graph [id name activities]) (defrecord Node [id name activities])

“活动”是一个列表

1 个答案:

答案 0 :(得分:3)

这可能是作弊,虽然它只有一行;)

(def tree {:id 1 :children [{:id 2 :children [{:id 3}]} {:id 4}]})

core> (filter #(= 3 (:id %)) (tree-seq :children :children tree)) 
({:id 3}) 

core> (filter #(= 2 (:id %)) (tree-seq :children :children tree))
({:children [{:id 3}], :id 2})

关于问题原始意图的一些观点:

  • loop / recer通常不是最紧凑的形式,通常用mapdoseq
  • 编写
  • 如果/ recur通常可以通过调用filter
  • 来替换
  • 如果您因某些特定要求似乎真的需要写这样的东西,通常zippers会更优雅地解决问题。