我正在将一些C ++代码转换为Clojure,我想要
返回图%C2%A0
,其中添加了许多边。
我输入了顶点数,图形和
测试谓词(例如,可能依赖于i,j,随机性等的函数)是这样的:
g
当然,问题在于(defn addSomeEdges [v g test-p]
(doseq [i (range v)]
(doseq [j (range (dec i))]
(if test-p
(add-edges g [i j] )
)))
g)
返回新的(add-edges)
。请问如何使用最佳实践Clojure捕获此更新的图形?在C ++中看起来是如此简单自然。
答案 0 :(得分:3)
将信息分成两部分,以迭代方式积累信息就好像是一种归约函数:
可以使用reduce
user> (defn add-edge [g i j]
(assoc g i j))
#'user/add-edge
user> (add-edge {1 2} 2 1)
{1 2, 2 1}
user> (defn addSomeEdges [v g test-p]
(reduce (fn [graph [i j]] ;; this takes the current graph, the points,
(if (test-p graph i j) ;; decides if the edge should be created.
(add-edge graph i j) ;; and returns the next graph
graph)) ;; or returns the graph unchanged.
g ;; This is the initial graph
(for [i (range v)
j (range (dec i))]
[i j]))) ;; this generates the candidate edges to check.
#'user/addSomeEdges
让我们运行它!
user> (addSomeEdges 4 {1 2} (fn [g i j] (rand-nth [true false])))
{1 2, 2 0}
user> (addSomeEdges 4 {1 2} (fn [g i j] (rand-nth [true false])))
{1 2, 3 0}
user> (addSomeEdges 4 {1 2} (fn [g i j] (rand-nth [true false])))
{1 2, 2 0, 3 1}
当您想到其他测试时,可以将这些调用组合在一起:
user> (as-> {1 2} g
(addSomeEdges 4 g (fn [g i j] (rand-nth [true false])))
(addSomeEdges 7 g (fn [g i j] (< i j)))
(addSomeEdges 9 g (fn [g i j] (contains? (set (keys g)) j))))
{1 2, 3 1, 4 1, 5 3, 6 4, 7 5, 8 6}
答案 1 :(得分:0)
对此有多种解决方案。但是,有时候,当您遇到根本上可变/必须的问题时,应该只使用可变/必要的解决方案:
; simplest version using mutation
(defn addSomeEdges [v g test-p]
(let [g-local (atom g)]
(doseq [i (range v)]
(doseq [j (range (dec i))]
(when (test-p i j ...) ; what other args does this need?
(swap! g-local add-edges [i j]))))
@g-local))
我对test-p
的对称性不太确定,因此该部分可能需要改进。
请注意,swap!
会这样呼叫add-edges
:
(add-edges <curr val of g-local> [i j])
有关更多信息,请参见the Clojure CheatSheet和ClojureDocs.org。