Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/jsf-2/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Clojure 如何识别对象的子集?_Clojure_Iterator_Combinatorics - Fatal编程技术网

Clojure 如何识别对象的子集?

Clojure 如何识别对象的子集?,clojure,iterator,combinatorics,Clojure,Iterator,Combinatorics,我如何在Clojure中最好地迭代下面的对象 { :item-set-1 ["a" "b" "c"] :item-set-2 ["d" "e" "f"] } 我想尝试识别对象的所有子集,并产生如下结果: { [:item-set-1 ["a"]] [:item-set-1 ["a" "b"]] [:item-set-1 ["a" "b" "c"]] [:item-set-1 ["b"]] [:item-set-1 ["b" "c"]] [:item-set-1 ["c"]]

我如何在Clojure中最好地迭代下面的对象

{
  :item-set-1 ["a" "b" "c"]
  :item-set-2 ["d" "e" "f"]
}
我想尝试识别对象的所有子集,并产生如下结果:

{
 [:item-set-1 ["a"]]
 [:item-set-1 ["a" "b"]]
 [:item-set-1 ["a" "b" "c"]]
 [:item-set-1 ["b"]]
 [:item-set-1 ["b" "c"]]
 [:item-set-1 ["c"]]
 [:item-set-2 ["d"]]
 [:item-set-2 ["d" "e"]]
 [:item-set-2 ["d" "e" "f"]]
 [:item-set-1 ["e"]]
 [:item-set-1 ["e" "f"]]
 [:item-set-1 ["f"]]

 [:item-set-1 ["a"] [:item-set-2 ["d"]]]
 [:item-set-1 ["b"] [:item-set-2 ["e"]]]
 [:item-set-1 ["c"] [:item-set-2 ["f"]]]

 [:item-set-1 ["a" "b"] [:item-set-2 ["d" "e"]]]
 [:item-set-1 ["a" "b"] [:item-set-2 ["e" "f"]]]
 [:item-set-1 ["a" "b"] [:item-set-2 ["d" "f"]]]
 [:item-set-1 ["b" "c"] [:item-set-2 ["d" "e"]]]
 [:item-set-1 ["b" "c"] [:item-set-2 ["e" "f"]]]
 [:item-set-1 ["b" "c"] [:item-set-2 ["d" "f"]]]
 [:item-set-1 ["a" "c"] [:item-set-2 ["d" "e"]]]
 [:item-set-1 ["a" "c"] [:item-set-2 ["e" "f"]]]
 [:item-set-1 ["a" "c"] [:item-set-2 ["d" "f"]]]

 [:item-set-1 ["a" "b" "c"] [:item-set-2 ["d" "e" "f"]]]
}
我相信我可以使用
clojure.math.combinationics
识别每个键中的子集,但不能识别整个对象

更新: 我试图用以下代码生成子集:

(defn generate-freq-item-set []
  (let [result [{:data (generate-string {:item-set-1 ["a" "b" "c"] :item-set-2 ["d" "e" "f"]})}]
        items (as-> () items
                    (->> (for [row result]
                           (for [data (parse-string (:data row))]
                              (for [subset (combo/subsets (second data))]
                               (conj items {(first data) subset}))))))
        frequencies (sort-by last >
                             (->> (apply concat (apply concat (apply concat items)))
                                      (frequencies)))]
      (prn frequencies)))
但这会产生以下输出,这与我所追求的并不完全相同:

([{"item-set-1" ()} 1] 
 [{"item-set-2" ("d")} 1] 
 [{"item-set-1" ("a" "b" "c")} 1] 
 [{"item-set-2" ("d" "e")} 1] 
 [{"item-set-1" ("b" "c")} 1] 
 [{"item-set-2" ("d" "e" "f")} 1] 
 [{"item-set-2" ()} 1] 
 [{"item-set-1" ("a" "b")} 1] 
 [{"item-set-1" ("c")} 1] 
 [{"item-set-2" ("e")} 1] 
 [{"item-set-2" ("d" "f")} 1] 
 [{"item-set-2" ("f")} 1] 
 [{"item-set-2" ("e" "f")} 1] 
 [{"item-set-1" ("b")} 1] 
 [{"item-set-1" ("a")} 1] 
 [{"item-set-1" ("a" "c")} 1])

我现在没有安装clojure,但在essense中,您需要这样做: 1) 将子集函数映射到每个项集。您将得到包含所有子集的两个集。 2) 将笛卡尔积应用于这两组子集。就这样。笛卡尔积取两个集合并输出所有可能的组合

一旦我下班并安装了clojure,我会给你回电话的


编辑

终于到家了,代码如下:

(require '[clojure.math.combinatorics :as combo])

(def inputdata {:item-set-1 ["a" "b" "c"] :item-set-2 ["d" "e" "f"]})

(defn subsets-without-empty [set] (filter not-empty (combo/subsets set)))

(defn to-subset-maps [kv] 
  (map (fn [v] {(key kv) v})
  (subsets-without-empty (val kv))))

(defn create-subsets [dictOfSets] (map to-subset-maps dictOfSets))

(apply combo/cartesian-product (create-subsets inputdata))
不带空的子集
按照您的建议获取除空子集以外的所有子集

到子集映射
{:a[12]}
转换为
[{:a[1]}{:a[2]}{:a[12]}]
,即创建子集并将原始密钥传播到每个子集(输出格式所需)

创建子集
仅将
应用于输入映射的每个成员的子集映射


最后,我们在一个集合中得到了结果。因此,我们只需要将其展开并传递到
笛卡尔积
,以获得所有的组合,这就是
apply
的最后一行。现在,此解决方案适用于任意数量的维度(或输入地图中的键)。

我现在没有安装clojure,但在essense中,您需要这样做: 1) 将子集函数映射到每个项集。您将得到包含所有子集的两个集。 2) 将笛卡尔积应用于这两组子集。就这样。笛卡尔积取两个集合并输出所有可能的组合

一旦我下班并安装了clojure,我会给你回电话的


编辑

终于到家了,代码如下:

(require '[clojure.math.combinatorics :as combo])

(def inputdata {:item-set-1 ["a" "b" "c"] :item-set-2 ["d" "e" "f"]})

(defn subsets-without-empty [set] (filter not-empty (combo/subsets set)))

(defn to-subset-maps [kv] 
  (map (fn [v] {(key kv) v})
  (subsets-without-empty (val kv))))

(defn create-subsets [dictOfSets] (map to-subset-maps dictOfSets))

(apply combo/cartesian-product (create-subsets inputdata))
不带空的子集
按照您的建议获取除空子集以外的所有子集

到子集映射
{:a[12]}
转换为
[{:a[1]}{:a[2]}{:a[12]}]
,即创建子集并将原始密钥传播到每个子集(输出格式所需)

创建子集
仅将
应用于输入映射的每个成员的子集映射


最后,我们在一个集合中得到了结果。因此,我们只需要将其展开并传递到
笛卡尔积
,以获得所有的组合,这就是
apply
的最后一行。现在,此解决方案适用于任意数量的维度(或输入地图中的键)。

我将按如下方式处理此问题

首先,我会将您拥有的初始映射拼接到一个列表中,将项目所属集合的信息保存在元数据中

由于无法将元数据附加到原始字符串,我们需要创建一个包装器类型:

(defrecord ItemSetElement [x])

(defn make-item-set-element [x]
  (->ItemSetElement x))

(defn unwrap-item-set-element [elem]
  (:x elem))
然后转到将初始映射转换为序列的函数,保存所需信息:

(defn wrap-element-and-save-owner [owner s]
  (with-meta (make-item-set-element s) {::owner owner}))

(defn prepare-data [data]
  (mapcat
   (fn [[key ss]]
     (map (partial wrap-element-and-save-owner key) ss))
   data))

> (prepare-data {:item-set-1 ["a" "b"], :item-set-2 ["c"]})
({:x "a"} {:x "b"} {:x "c"})
如您所见,
prepare data
的结果只是一个序列,但序列的每个元素在其元中都有关于“所有者”集的信息,例如:

> (meta (first (prepare-data {:item-set-1 ["a" "b"], :item-set-2 ["c"]})))
{:user/owner :item-set-1}
有了序列,我们可以使用
clojure.math.combinationics/subsets
生成它的所有子集:

> (require '[clojure.math.combinatorics :as combo])
nil
> (combo/subsets (prepare-data {:item-set-1 ["a" "b"], :item-set-2 ["c"]}))
(()
 ({:x "a"})
 ({:x "b"})
 ({:x "c"})
 ({:x "a"} {:x "b"})
 ({:x "a"} {:x "c"})
 ({:x "b"} {:x "c"})
 ({:x "a"} {:x "b"} {:x "c"}))
子集的每个元素仍然有关于其“所有者”的信息,因此我们可以轻松地将其转换为类似于初始结构的结构。这里有一个函数:

(defn reconstruct-item-sets [subset]
  (->> subset
       (group-by #(::owner (meta %)))
       (map (fn [[key elements]]
              [key (map unwrap-item-set-element elements)]))
       (into {})))
总而言之,这里是所有代码,包括函数,它们将所有内容粘合在一起:

(require '[clojure.math.combinatorics :as combo])

(defrecord ItemSetElement [x])

(defn make-item-set-element [x]
  (->ItemSetElement x))

(defn unwrap-item-set-element [elem]
  (:x elem))

(defn wrap-element-and-save-owner [owner s]
  (with-meta (make-item-set-element s) {::owner owner}))

(defn prepare-data [data]
  (mapcat
   (fn [[key ss]]
     (map (partial wrap-element-and-save-owner key) ss))
   data))

(defn reconstruct-item-sets [subset]
  (->> subset
       (group-by #(::owner (meta %)))
       (map (fn [[key elements]]
              [key (map unwrap-item-set-element elements)]))
       (into {})))

 (defn my-subsets [data]
   (->> data
        prepare-data
        combo/subsets
        (map reconstruct-item-sets)))

(def data {:item-set-1 ["a" "b"]
           :item-set-2 ["c" "d" "e"]})

> (my-subsets data)
({}
 {:item-set-1 ("a")}
 {:item-set-1 ("b")}
 {:item-set-2 ("c")}
 {:item-set-2 ("d")}
 {:item-set-2 ("e")}
 {:item-set-1 ("a" "b")}
 {:item-set-1 ("a"), :item-set-2 ("c")}
 {:item-set-1 ("a"), :item-set-2 ("d")}
 {:item-set-1 ("a"), :item-set-2 ("e")}
 {:item-set-1 ("b"), :item-set-2 ("c")}
 {:item-set-1 ("b"), :item-set-2 ("d")}
 {:item-set-1 ("b"), :item-set-2 ("e")}
 {:item-set-2 ("c" "d")}
 {:item-set-2 ("c" "e")}
 {:item-set-2 ("d" "e")}
 {:item-set-1 ("a" "b"), :item-set-2 ("c")}
 {:item-set-1 ("a" "b"), :item-set-2 ("d")}
 {:item-set-1 ("a" "b"), :item-set-2 ("e")}
 {:item-set-1 ("a"), :item-set-2 ("c" "d")}
 {:item-set-1 ("a"), :item-set-2 ("c" "e")}
 {:item-set-1 ("a"), :item-set-2 ("d" "e")}
 {:item-set-1 ("b"), :item-set-2 ("c" "d")}
 {:item-set-1 ("b"), :item-set-2 ("c" "e")}
 {:item-set-1 ("b"), :item-set-2 ("d" "e")}
 {:item-set-2 ("c" "d" "e")}
 {:item-set-1 ("a" "b"), :item-set-2 ("c" "d")}
 {:item-set-1 ("a" "b"), :item-set-2 ("c" "e")}
 {:item-set-1 ("a" "b"), :item-set-2 ("d" "e")}
 {:item-set-1 ("a"), :item-set-2 ("c" "d" "e")}
 {:item-set-1 ("b"), :item-set-2 ("c" "d" "e")}
 {:item-set-1 ("a" "b"), :item-set-2 ("c" "d" "e")})

我将按如下方式处理这个问题

首先,我会将您拥有的初始映射拼接到一个列表中,将项目所属集合的信息保存在元数据中

由于无法将元数据附加到原始字符串,我们需要创建一个包装器类型:

(defrecord ItemSetElement [x])

(defn make-item-set-element [x]
  (->ItemSetElement x))

(defn unwrap-item-set-element [elem]
  (:x elem))
然后转到将初始映射转换为序列的函数,保存所需信息:

(defn wrap-element-and-save-owner [owner s]
  (with-meta (make-item-set-element s) {::owner owner}))

(defn prepare-data [data]
  (mapcat
   (fn [[key ss]]
     (map (partial wrap-element-and-save-owner key) ss))
   data))

> (prepare-data {:item-set-1 ["a" "b"], :item-set-2 ["c"]})
({:x "a"} {:x "b"} {:x "c"})
如您所见,
prepare data
的结果只是一个序列,但序列的每个元素在其元中都有关于“所有者”集的信息,例如:

> (meta (first (prepare-data {:item-set-1 ["a" "b"], :item-set-2 ["c"]})))
{:user/owner :item-set-1}
有了序列,我们可以使用
clojure.math.combinationics/subsets
生成它的所有子集:

> (require '[clojure.math.combinatorics :as combo])
nil
> (combo/subsets (prepare-data {:item-set-1 ["a" "b"], :item-set-2 ["c"]}))
(()
 ({:x "a"})
 ({:x "b"})
 ({:x "c"})
 ({:x "a"} {:x "b"})
 ({:x "a"} {:x "c"})
 ({:x "b"} {:x "c"})
 ({:x "a"} {:x "b"} {:x "c"}))
子集的每个元素仍然有关于其“所有者”的信息,因此我们可以轻松地将其转换为类似于初始结构的结构。这里有一个函数:

(defn reconstruct-item-sets [subset]
  (->> subset
       (group-by #(::owner (meta %)))
       (map (fn [[key elements]]
              [key (map unwrap-item-set-element elements)]))
       (into {})))
总而言之,这里是所有代码,包括函数,它们将所有内容粘合在一起:

(require '[clojure.math.combinatorics :as combo])

(defrecord ItemSetElement [x])

(defn make-item-set-element [x]
  (->ItemSetElement x))

(defn unwrap-item-set-element [elem]
  (:x elem))

(defn wrap-element-and-save-owner [owner s]
  (with-meta (make-item-set-element s) {::owner owner}))

(defn prepare-data [data]
  (mapcat
   (fn [[key ss]]
     (map (partial wrap-element-and-save-owner key) ss))
   data))

(defn reconstruct-item-sets [subset]
  (->> subset
       (group-by #(::owner (meta %)))
       (map (fn [[key elements]]
              [key (map unwrap-item-set-element elements)]))
       (into {})))

 (defn my-subsets [data]
   (->> data
        prepare-data
        combo/subsets
        (map reconstruct-item-sets)))

(def data {:item-set-1 ["a" "b"]
           :item-set-2 ["c" "d" "e"]})

> (my-subsets data)
({}
 {:item-set-1 ("a")}
 {:item-set-1 ("b")}
 {:item-set-2 ("c")}
 {:item-set-2 ("d")}
 {:item-set-2 ("e")}
 {:item-set-1 ("a" "b")}
 {:item-set-1 ("a"), :item-set-2 ("c")}
 {:item-set-1 ("a"), :item-set-2 ("d")}
 {:item-set-1 ("a"), :item-set-2 ("e")}
 {:item-set-1 ("b"), :item-set-2 ("c")}
 {:item-set-1 ("b"), :item-set-2 ("d")}
 {:item-set-1 ("b"), :item-set-2 ("e")}
 {:item-set-2 ("c" "d")}
 {:item-set-2 ("c" "e")}
 {:item-set-2 ("d" "e")}
 {:item-set-1 ("a" "b"), :item-set-2 ("c")}
 {:item-set-1 ("a" "b"), :item-set-2 ("d")}
 {:item-set-1 ("a" "b"), :item-set-2 ("e")}
 {:item-set-1 ("a"), :item-set-2 ("c" "d")}
 {:item-set-1 ("a"), :item-set-2 ("c" "e")}
 {:item-set-1 ("a"), :item-set-2 ("d" "e")}
 {:item-set-1 ("b"), :item-set-2 ("c" "d")}
 {:item-set-1 ("b"), :item-set-2 ("c" "e")}
 {:item-set-1 ("b"), :item-set-2 ("d" "e")}
 {:item-set-2 ("c" "d" "e")}
 {:item-set-1 ("a" "b"), :item-set-2 ("c" "d")}
 {:item-set-1 ("a" "b"), :item-set-2 ("c" "e")}
 {:item-set-1 ("a" "b"), :item-set-2 ("d" "e")}
 {:item-set-1 ("a"), :item-set-2 ("c" "d" "e")}
 {:item-set-1 ("b"), :item-set-2 ("c" "d" "e")}
 {:item-set-1 ("a" "b"), :item-set-2 ("c" "d" "e")})

UH我是否正确理解了您发送的“像这样的结果”只包含部分结果,而不是全部结果?例如,
[:item-set-1[“a”“c”][:item-set-2[“d”“f”]]]
缺失…@netchkin我在我的示例中遗漏了这一点。我已经更新了这个问题。长度=1怎么样?它不是也必须包含[“a”][“e”]、[“a”][“f”]等的对吗?所有的子集-我认为它也意味着例如[:item-set-1[“c”][:item-set-2[“d”“e”]]。。。我是否正确理解了您发送的“像这样的结果”只包含部分结果,而不是全部结果?例如,
[:item-set-1[“a”“c”][:item-set-2[“d”“f”]]]
缺失…@netchkin我在我的示例中遗漏了这一点。我已经更新了这个问题。长度=1怎么样?它不是也必须包含[“a”][“e”]、[“a”][“f”]等的对吗?所有的子集-我想它也意味着例如[:item-set-1[“c”][:item-set-2[“d”“e”]]。谢谢你给出这样详细的答案!谢谢你这么详细的回答!