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))