在clojure中构建表

时间:2013-11-21 02:11:35

标签: clojure clojure-contrib

如果我想在矢量重复的Clojure中构建一个表,我会写:

(take 2 (repeat [1 2 3]))

但是我如何扩展这个表函数的概念来构建类似的东西:

输入1:[a ^ 2 2 6 2]其中a ^ 2是某个输入函数,2是最小值,6是最大值,2是步长。

输出1:[4,16,36]

输入2:[b ^ 2 10 -5 -2]

输出2:[100 64 36 16 4 0 4 16]

输出4x3矩阵

输入3:[(+(* 10 i)j)[1 4] [1 3]]

其中(+(* 10 i)j)是10i + j(某些给定的输入函数),[1 4]是i的最小值和最大值,[1 3]是j的最小值和最大值。

产出3:[[11 12 13] [21 22 23] [31 32 33] [41 42 43]]

3 个答案:

答案 0 :(得分:1)

您希望以嵌套方式使用for

(for [i (range 1 (inc 4))]
  (for [j (range 1 (inc 3))]
    (+ (* 10 i) j)))
;; '((11 12 13) (21 22 23) (31 32 33) (41 42 43))

编辑扩展了一个示例实现

例如:

(defn build-seq [f lower upper step]
  (for [i (range lower (+ upper step) step)]
    (f i)))

(build-seq #(* % %) 2 6 2)
;; '(4 16 36)

(defn build-table [f [ilower iupper] [jlower jupper]]
  (for [i (range ilower (inc iupper))]
    (for [j (range jlower (inc jupper))]
      (f i j))))

(build-table #(+ (* 10 %) %2) [1 4] [1 3])
;; '((11 12 13) (21 22 23) (31 32 33) (41 42 43))

您的三个输入/输出样本不会为一个变量和两个变量显示一致的签名;此外,step参数似乎是可选的。我对保留样本语法的漂亮API的存在持怀疑态度,但我可以尝试不同的东西(即使我确实认为简单的嵌入式for形式是更好的解决方案):

(defn flexible-range [{:keys [lower upper step] :or {lower 0}}]
  (let [[upper step] (cond
                       (and upper step) [(+ upper step) step]
                       step  (if (pos? step)
                               [Double/POSITIVE_INFINITY step]
                               [Double/NEGATIVE-INFINITY step])
                       upper (if (< lower upper)
                               [(inc upper)  1]
                               [(dec upper) -1])
                       :else   [Double/POSITIVE_INFINITY 1])]
    (range lower upper step)))

(defn build-table
  ([f [& params]]
    (for [i (flexible-range params)]
      (f i)))
  ([f [& iparams] [& jparams]]
    (for [i (flexible-range iparams)]
      (for [j (flexible-range jparams)]
        (f i j)))))

(build-table #(* % %) [:lower 2 :upper 6 :step  2])
;; '(4 16 36)

(build-table #(+ (* 10 %) %2) [:lower 1 :upper 4]
                              [:lower 1 :upper 3])
;; '((11 12 13) (21 22 23) (31 32 33) (41 42 43))

答案 1 :(得分:0)

我认为您可以使用maprange

轻松解决问题
(defn applier
  [f ini max step]
  (map f (range ini (+ max step) step)))

(applier #(* % %) 2 6 2)
=> (4 16 36)

答案 2 :(得分:0)

这个fn可以解决你的第三个例子

(defn your-fn [[ra1 ra2] [rb1 rb2] the-fn]
   (vec (map (fn [i] (vec (map (fn [j] (the-fn i j)) (range rb1 (inc rb2))))) (range ra1 (inc ra2))))
   )
(your-fn [1 4] [1 3] (fn [i j] (+ (* 10 i) j)))

=> [[11 12 13] [21 22 23] [31 32 33] [41 42 43]]

但是我需要更多规范细节(或更多用例)来使这种行为变得通用,也许你可以解释一下你的问题。我认为第1和第2个例子不采用相同类型的参数和含义,(步骤与seq)。因此,@ Guillermo-Winkler解决了问题,而my-fn将涵盖最后一个例子