我正在找出解决问题的方法,但我觉得它不会很有效率。我有一个可变长度数组的二维单元结构,在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循环/重复之外,还有一种更聪明的方法。可能有一些简化函数,通过使用累加器简化语法。
答案 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
按照正确的顺序(增加)时才有效,因为您不能conj
或assoc
进入除了一端以外的任何地方的向量
我还认为使用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项目,该项目提供了处理数据集等的例程。