将多维单元数组的生成从Matlab转换为Clojure的最佳方法是什么?

时间:2010-09-29 17:21:48

标签: matlab clojure

我正在找出解决问题的方法,但我觉得它不会很有效率。我有一个可变长度数组的二维单元结构,在Matlab中以非常无功能的方式构造,我想将其转换为Clojure。这是我正在尝试做的一个例子:

pre = cell(N,1);
aux = cell(N,1);
for i=1:Ne
  for j=1:D
    for k=1:length(delays{i,j})
        pre{post(i, delays{i, j}(k))}(end+1) = N*(delays{i, j}(k)-1)+i;
        aux{post(i, delays{i, j}(k))}(end+1) = N*(D-1-j)+i; % takes into account delay
    end;
  end;
end;

我目前的实施计划是使用3个循环,其中第一个用一个空向量的N个向量的向量进行初始化。每个子循环由前一个循环初始化。我定义了一个单独的函数,它接受整个向量和子指数和值,并返回带有更新子向量的向量。

除了使用3循环/重复之外,还有一种更聪明的方法。可能有一些简化函数,通过使用累加器简化语法。

2 个答案:

答案 0 :(得分:2)

我不是100%确定我理解你的代码在做什么(我不知道Matlab),但这可能是构建多维向量的一种方法:

(defn conj-in
  "Based on clojure.core/assoc-in, but with vectors instead of maps."
  [coll [k & ks] v]
  (if ks
    (assoc coll k (conj-in (get coll k []) ks v))
    (assoc coll k v)))

(defn foo []
  (let [w 5, h 4, d 3
        indices (for [i (range w)
                      j (range h)
                      k (range d)]
                  [i j k])]
    (reduce (fn [acc [i j k :as index]]
              (conj-in acc index
                       ;; do real work here
                       (str i j k)))
            [] indices)))

user> (pprint (foo))
[[["000" "001" "002"]
  ["010" "011" "012"]
  ["020" "021" "022"]
  ["030" "031" "032"]]
 [["100" "101" "102"]
  ["110" "111" "112"]
  ["120" "121" "122"]
  ["130" "131" "132"]]
 [["200" "201" "202"]
  ["210" "211" "212"]
  ["220" "221" "222"]
  ["230" "231" "232"]]
 [["300" "301" "302"]
  ["310" "311" "312"]
  ["320" "321" "322"]
  ["330" "331" "332"]]
 [["400" "401" "402"]
  ["410" "411" "412"]
  ["420" "421" "422"]
  ["430" "431" "432"]]]

仅当indices按照正确的顺序(增加)时才有效,因为您不能conjassoc进入除了一端以外的任何地方的向量

我还认为使用make-array并通过aset构建数组是可以接受的。这就是为什么Clojure提供对Java可变数组的访问;有些算法更优雅,有时你需要它们来提高性能。如果你想避免泄漏副作用,你可以在完成后将数据转储到Clojure向量中。

(我不知道这个或其他版本中的哪个版本表现更好。)

(defn bar []
  (let [w 5, h 4, d 3
        arr (make-array String w h d)]
    (doseq [i (range w)
            j (range h)
            k (range d)]
      (aset arr i j k (str i j k)))
    (vec (map #(vec (map vec %)) arr))))  ;yikes?

答案 1 :(得分:1)

查看Incanter项目,该项目提供了处理数据集等的例程。