我有一个函数,给定一个向量,返回所有无序组合:
(defn combination [ps]
(loop [acc []
ps ps]
(if (= 2 (count ps))
(conj acc (apply vector ps))
(recur (apply conj acc (map #(vector (first ps) %) (rest ps)))
(rest ps)))))
这很好用,但对我来说似乎有点费解。
在Clojure中有没有更直接,惯用的方法来实现这一目标?我很高兴使用Clojure核心或库函数,因为这肯定是我对“惯用语”定义的一部分。 :)
答案 0 :(得分:3)
Clojure有 clojure.math.combinatorics ,它包含许多方便的功能。所以可以说是"惯用的"你在Clojure做的事情的方法是导入/要求 clojure.math.combinatorics ,然后只需用 n = 2来调用组合。
...> (comb/combinations [1 2 3 4] 2)
((1 2) (1 3) (1 4) (2 3) (2 4) (3 4))
为此,您需要先添加正确的依赖项。
在我写这篇文章时,最新版本为:[org.clojure/math.combinatorics "0.0.7"]
我确实需要它" :as comb
":
(:require [clojure.math.combinatorics :as comb]
如果您不想使用 math.combinatorics ,您可以编辑问题以使其更加精确,我会删除我的答案。
答案 1 :(得分:1)
有些讽刺......
(defn combination [ps]
(clojure.math.combinatorics/combinations ps 2))
......这是懒惰的,但the source code是你的两倍或三倍。
答案 2 :(得分:1)
您的代码会返回按顺序获取的两个元素的所有选择。另一种方法是......
(defn combination [s]
(let [tails (take-while next (iterate rest s))]
(mapcat (fn [[f & rs]] (map #(vector f %) rs)) tails)))
这比你的短,而且也很懒。但它可能会变慢。