【问题标题】:What is the best way to translate the generation of a multidimensional cell array from Matlab to Clojure将多维单元数组的生成从 Matlab 转换为 Clojure 的最佳方法是什么
【发布时间】:2010-09-29 17:21:47
【问题描述】:

我正在为我的问题找到一个解决方案,但我感觉它不会很有效率。我有一个可变长度数组的二维单元结构,它在 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 函数。

【问题讨论】:

    标签: matlab clojure


    【解决方案1】:

    我不是 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?
    

    【讨论】:

    • 我不确定我是否会使用资产或功能更强大的版本......但是我想功能数组设置可以变成简化事情的宏或函数。谢谢。
    【解决方案2】:

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

    【讨论】:

      猜你喜欢
      • 2023-03-23
      • 1970-01-01
      • 1970-01-01
      • 2021-05-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-19
      • 1970-01-01
      相关资源
      最近更新 更多