我是Clojure的新手,我很难习惯性地使用数据结构实现基本操作.
在Clojure中实现以下代码的惯用方法是什么?
l = [...] for i in range(len(l)): for j in range(i + 1, len(l)): print l[i], l[j]
leetwinski.. 5
最简单的(但不是最多的FP-ish)几乎与你的例子相同:
(let [v [1 2 3 4 5 6 7]] (doseq [i (range (count v)) j (range (inc i) (count v))] (println (v i) (v j))))
这里是生成所有这些对的更多功能变体(它不是基于长度或索引,而是基于尾部迭代):
(let [v [1 2 3 4 5 6 7]] (mapcat #(map (partial vector (first %)) (rest %)) (take-while not-empty (iterate rest v))))
输出:
([1 2] [1 3] [1 4] [1 5] [1 6] [1 7] [2 3] [2 4] [2 5] [2 6] [2 7] [3 4] [3 5] [3 6] [3 7] [4 5] [4 6] [4 7] [5 6] [5 7] [6 7])
然后只需使用这些配对产生doseq
任何副作用:
(let [v [1 2 3 4 5 6 7] pairs (fn [items-seq] (mapcat #(map (partial vector (first %)) (rest %)) (take-while not-empty (iterate rest items-seq))))] (doseq [[i1 i2] (pairs v)] (println i1 i2)))
更新:关注@ dg123的答案.这很好,但是你可以使用doseq
和for
s和解构和保护等功能让它变得更好:
(let [v [1 2 3 4 5 6 7]] (doseq [[x & xs] (iterate rest v) :while xs y xs] (println "x:" x "y:" y)))
你迭代一个集合的尾巴,但请记住,这iterate
会产生一个无限的coll:
user> (take 10 (iterate rest [1 2 3 4 5 6 7])) ([1 2 3 4 5 6 7] (2 3 4 5 6 7) (3 4 5 6 7) (4 5 6 7) (5 6 7) (6 7) (7) () () ())
所以你必须以某种方式限制它只包括非空集合.解构形式[x & xs]
将参数拆分为第一个参数和其余参数的序列:
user> (let [[x & xs] [1 2 3 4 5 6]] (println x xs)) 1 (2 3 4 5 6) nil
当绑定的集合为空或具有单个元素时,xs
将是nil
:
user> (let [[x & xs] [1]] (println x xs)) 1 nil nil
所以你只需要使用这个功能,:while
在列表理解中使用guard.
最后你只需构建对(或在这种情况下做一些副作用)x
和每个项目xs
最简单的(但不是最多的FP-ish)几乎与你的例子相同:
(let [v [1 2 3 4 5 6 7]] (doseq [i (range (count v)) j (range (inc i) (count v))] (println (v i) (v j))))
这里是生成所有这些对的更多功能变体(它不是基于长度或索引,而是基于尾部迭代):
(let [v [1 2 3 4 5 6 7]] (mapcat #(map (partial vector (first %)) (rest %)) (take-while not-empty (iterate rest v))))
输出:
([1 2] [1 3] [1 4] [1 5] [1 6] [1 7] [2 3] [2 4] [2 5] [2 6] [2 7] [3 4] [3 5] [3 6] [3 7] [4 5] [4 6] [4 7] [5 6] [5 7] [6 7])
然后只需使用这些配对产生doseq
任何副作用:
(let [v [1 2 3 4 5 6 7] pairs (fn [items-seq] (mapcat #(map (partial vector (first %)) (rest %)) (take-while not-empty (iterate rest items-seq))))] (doseq [[i1 i2] (pairs v)] (println i1 i2)))
更新:关注@ dg123的答案.这很好,但是你可以使用doseq
和for
s和解构和保护等功能让它变得更好:
(let [v [1 2 3 4 5 6 7]] (doseq [[x & xs] (iterate rest v) :while xs y xs] (println "x:" x "y:" y)))
你迭代一个集合的尾巴,但请记住,这iterate
会产生一个无限的coll:
user> (take 10 (iterate rest [1 2 3 4 5 6 7])) ([1 2 3 4 5 6 7] (2 3 4 5 6 7) (3 4 5 6 7) (4 5 6 7) (5 6 7) (6 7) (7) () () ())
所以你必须以某种方式限制它只包括非空集合.解构形式[x & xs]
将参数拆分为第一个参数和其余参数的序列:
user> (let [[x & xs] [1 2 3 4 5 6]] (println x xs)) 1 (2 3 4 5 6) nil
当绑定的集合为空或具有单个元素时,xs
将是nil
:
user> (let [[x & xs] [1]] (println x xs)) 1 nil nil
所以你只需要使用这个功能,:while
在列表理解中使用guard.
最后你只需构建对(或在这种情况下做一些副作用)x
和每个项目xs