Pergunta

I have two seqs h-keys and h-values. I need to build up a seq of all possible maps that assoc n elements from h-keys with elements from h-values.

(def h-keys [:a :b :c])
(def h-values [1 2])
(def res (f h-keys h-values 2))
(= (set res) #{{:a 1, :b 1} {:a 1 :b 2} {:a 2 :b 1} {:a 2 :b 2} {:a 1, :c 1} {:a 1 :c 2} {:a 2 :c 1} {:a 2 :c 2} {:c 1, :b 1} {:c 1 :b 2} {:c 2 :b 1} {:c 2 :b 2}})

How would I go about writing f?

Foi útil?

Solução

Alternative implementation using combinatorics

 (require '[clojure.math.combinatorics :as combo])
 (defn f 
   [keys vals n]
   (->> (combo/cartesian-product (combo/combinations keys n)
                                 (combo/selections vals n))
        (map (partial apply zipmap))
        set))

> (f [:a :b :c] [1 2] 2)
=> #{{:c 2, :a 1} {:c 1, :a 1} {:c 2, :a 2} {:b 1, :a 1} {:c 1, :a 2} {:b 2, :a 1} {:c 2, :b 1} {:c 1, :b 1} {:c 2, :b 2} {:b 1, :a 2} {:c 1, :b 2} {:b 2, :a 2}}

Outras dicas

(require '[clojure.math.combinatorics :as combo])
(defn f [keys values n]
  (set (for [res-keys (combo/combinations keys n)
             res-values (combo/selections values n)]
            (zipmap res-keys res-values))))
(require '[clojure.math.combinatorics :as combo])

(defn f [keys values n]
  (mapcat (fn [keys]
            (map (fn [values]
                   (apply assoc {} (interleave keys values)))
                 (combo/selections values n)))
          (combo/combinations keys n)))
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top