登录论坛

查看完整版本 : 将多维单元阵列的生成从Matlab转换为Clojure的最佳方法是什么


poster
2019-12-10, 20:48
我正在为我的问题找出一个解决方案,但是我感觉它不会很有效。我有一个可变长度数组的二维单元结构,该结构在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循环/重复,必须有一种更聪明的方法。可能有一些reduce函数通过使用累加器来简化语法。



回答:

我不是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 kv))) (defn foo [] (let [w 5, h 4, d 3 indices (for [i (range w) j (range h) k (range d)] [ijk])] (reduce (fn [acc [ijk :as index]] (conj-in acc index ;; do real work here (str ijk))) [] 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 whd)] (doseq [i (range w) j (range h) k (range d)] (aset arr ijk (str ijk))) (vec (map #(vec (map vec %)) arr)))) ;yikes?

更多&回答... (https://stackoverflow.com/questions/3824200)