Clojure:适用于n维度

Ant*_*ald 4 clojure clojurescript

在Clojure中,该函数for可用于迭代嵌套序列.想象一下具有x轴,y轴和z轴的3D空间:

(for [x (range 10)
      y (range 5)
      z (range 2)]
    [x y z])
Run Code Online (Sandbox Code Playgroud)

上面的代码将产生一系列向量,表示长方体内的所有可能位置.(当然,限于指数是自然数的位置)

有没有人知道这个更通用的好方法?意思是,如果你没有3个但是有n个维度,那么它就可以了.

gal*_*dre 5

大多数 方法似乎都在使用for假设已知数量的维度.你似乎在寻找的是笛卡尔积.在clojure.math.combinatorics中有一个计算笛卡尔积的函数.

(cartesian-product (range 10) (range 5) (range 2))
(apply cartesian-product (map range [10 5 2]))
(apply cartesian-product (repeatedly n #(range 3)))
Run Code Online (Sandbox Code Playgroud)

如果您不想包含其他库,这个问题有一些您可以使用和/或学习的有趣答案.


截至2016年3月,这是以下来源clojure.math.combinatorics/cartesian-product:

(defn cartesian-product
  "All the ways to take one item from each sequence"
  [& seqs]
  (let [v-original-seqs (vec seqs)
        step
        (fn step [v-seqs]
          (let [increment
                (fn [v-seqs]
                  (loop [i (dec (count v-seqs)), v-seqs v-seqs]
                    (if (= i -1) nil
                      (if-let [rst (next (v-seqs i))]
                        (assoc v-seqs i rst)
                            (recur (dec i) (assoc v-seqs i (v-original-seqs i)))))))]
            (when v-seqs
              (cons (map first v-seqs)
                    (lazy-seq (step (increment v-seqs)))))))]
    (when (every? seq seqs)
      (lazy-seq (step v-original-seqs)))))
Run Code Online (Sandbox Code Playgroud)