clojure中集合的所有子集
我希望生成一个集合的所有子集,除了空集 即clojure中集合的所有子集,clojure,set,subset,combinatorics,Clojure,Set,Subset,Combinatorics,我希望生成一个集合的所有子集,除了空集 即 在clojure中如何做到这一点?在项目中的:依赖项。clj: [org.clojure/math.combinatorics "0.0.7"] 在REPL上: (require '[clojure.math.combinatorics :as combinatorics]) (->> #{1 2 3} (combinatorics/subsets) (remove empty?) (map set) (set)) ;=
在clojure中如何做到这一点?在
项目中的:依赖项。clj
:
[org.clojure/math.combinatorics "0.0.7"]
在REPL上:
(require '[clojure.math.combinatorics :as combinatorics])
(->> #{1 2 3}
(combinatorics/subsets)
(remove empty?)
(map set)
(set))
;= #{#{1} #{2} #{3} #{1 2} #{1 3} #{2 3} #{1 2 3}}
clojure.math.combinations/subsets
明智地返回一个序列,因此需要进行额外的转换以匹配所需的输出。请参阅:
);(所有子集#{1 2 3})
; (#{1}{2}{3}{12}{1 3}{1 2 3}{1 2 3})@zcaudate:为了完整性,这里有一个递归实现:
(defn subsets
[s]
(if (empty? s)
#{#{}}
(let [ts (subsets (rest s))]
(->> ts
(map #(conj % (first s)))
(clojure.set/union ts)))))
;; (subsets #{1 2 3})
;; => #{#{} #{1} #{2} #{3} #{1 2} #{1 3} #{2 3} #{1 2 3}} (which is correct).
这是一个简洁的尾部递归版本,只依赖于clojure.core
(defn power [s]
(loop [[f & r] (seq s) p '(())]
(if f (recur r (concat p (map (partial cons f) p)))
p)))
如果希望在一组集合中显示结果,请使用以下命令
(defn power-set [s] (set (map set (power s))))
这是@Brent M.Spell解决方案的一个细微变化,目的是寻求对惯用Clojure中性能考虑的启示
我只是想知道,在循环中构造子集而不是通过(map set…
进行另一次迭代是否会节省一些开销,特别是当集合非常大时
(defn power [s]
(set (loop [[f & r] (seq s) p '(#{})]
(if f (recur r (concat p (map #(conj % f) p)))
p))))
(power [1 2 3])
;; => #{#{} #{3} #{2} #{1} #{1 3 2} #{1 3} #{1 2} #{3 2}}
在我看来,loop
和recur
并不懒惰。
最好有一个像Brent这样的惰性评估版本,以保持表达式的优雅,同时使用惰性来实现效率
这个版本作为一个框架还有另一个优点,当有太多的子集需要计算时,它可以轻松地支持子集候选对象的修剪。可以在conj
位置添加修剪逻辑。我用它实现了“频繁项集”的先验算法 此版本松散地模仿了。我知道这个问题似乎已经合理地解决了。。。但不管怎样,给你
(fn [s]
(reduce
(fn [a b] (clojure.set/union a
(set (map (fn [y] (clojure.set/union #{b} y)) a))))
#{#{}} s))
通常,powerset也包含空集。我希望实现简单,而不是依赖于library@zcaudate:Clojure是一种图书馆语言。一个手写的实现来解决像这样的一般问题永远不是一个好主意,也不是一个好的实践,除非是为了学习。依靠像《数学与密码》这样的官方图书馆,组合数学没有任何取舍,通常比你手工所能做的一切都要好得多。如果有可能的话,你也可以期望致力于解决这个问题的人会改进它。我对这个答案唯一的质疑可能是使用了1和小写L作为变量名。不得不眯着眼睛看一看。
(defn power [s]
(set (loop [[f & r] (seq s) p '(#{})]
(if f (recur r (concat p (map #(conj % f) p)))
p))))
(power [1 2 3])
;; => #{#{} #{3} #{2} #{1} #{1 3 2} #{1 3} #{1 2} #{3 2}}
(fn [s]
(reduce
(fn [a b] (clojure.set/union a
(set (map (fn [y] (clojure.set/union #{b} y)) a))))
#{#{}} s))