Reputation: 560
I am trying to write a function in clojure returns cartesian product
(my-compute-fn [1 2 3] [4 5 6])
will return
[[1 4] [1 5] [1 6] [2 4] [2 5] ....]
My attempt resulted in this
(defn compute [col1 col2]
(let [totcol2 (count col2)
totcol1 (count col2)]
(map #(vector %1 %2)
(mapcat #(repeat totcol1 %1) col1)
(take (* totcol1 totcol2) (cycle col2)))))
Which does the job, but looks a bit clunky. What would be a better and more concise implementation, involving more readily available functions from clojure.core?
Thanks!
edit: Found clojure combinatorics, and it doesn't seem there's a magic functional way of doing this.
Upvotes: 1
Views: 484
Reputation: 6073
for
is the prime candidate for this task:
(for [a [1 2 3]
b [4 5 6]]
[a b])
;; => ([1 4] [1 5] [1 6] [2 4] [2 5] [2 6] [3 4] [3 5] [3 6])
You can supply for
with any number of seqs and it will bind the given symbols to each element of the seq associated with them. There is even cooler stuff like :when
that lets you e.g. find all those products whose sum is 7:
(for [a [1 2 3]
b [4 5 6]
:when (= (+ a b) 7)]
[a b])
;; => ([1 6] [2 5] [3 4])
Upvotes: 9