给定一个矩阵作为clojure中的向量向量:
(def A [[1 2 3 4]
[5 6 7 8]
[9 10 11 12]
[13 14 15 16]])
Run Code Online (Sandbox Code Playgroud)
我想把它分成四个季度:
'([[1 2]
[5 6]] ; tl
[[3 4]
[7 8]] ; tr
[[9 10]
[13 14]] ; bl
[[11 12]
[15 16]]) ;br
Run Code Online (Sandbox Code Playgroud)
这种愚蠢的方法是这样的(受到haskells子矩阵的启发):
(defn submatrix [A slice-col slice-row]
(let [tl (map (fn [col] (take slice-col col)) (take slice-row A))
tr (map (fn [col] (take slice-col col)) (drop slice-row A))
bl (map (fn [col] (drop slice-col col)) (take slice-row A))
br (map (fn [col] (drop slice-col col)) (drop slice-row A))]
(vector tl tr bl br))
)
Run Code Online (Sandbox Code Playgroud)
这是有效的(除了它基于列表而不是向量),但在函数式编程方面并不是很漂亮.
另一种方法让clojure感觉更自然,但让我陷入困境:
;; just a helper, simmilar to split-at but returns vectors instead
(defn split-at' [idx v] [(subvec v 0 idx) (subvec v idx)])
(defn mquarter [A]
(let [cuts (map (fn [col] (split-at' 1 col)) A)] ; 1 is just for testing and will be a parameter later ...
(prn cuts) ; do something clever here like (map (fn [row] .. take .. drop ..) cuts)
))
Run Code Online (Sandbox Code Playgroud)
如果我称之为它,就像(mquarter [[1 2 3 4] [5 6 7 8] [9 10 11 12] [13 14 15 16]])它给我一样([[1] [2 3 4]] [[5] [6 7 8]] [[9] [10 11 12]] [[13] [14 15 16]]).这很好,但我没有看到如何将切割合并到具有预期结构的新矢量.
是否有一种巧妙的方法将切割合并到包含我四个季度的预期结构中?期望的集合具有与输入向量完全不同的结构A,因此我想知道是否甚至可以像这样进行转换 A.
注意:我知道有些库已经在做这个,我想这样做是为了学习clojure.
更新:我对所提出的方法http://git.io/lAZ5OA进行了快速的性能比较,结果如下:
Elapsed time: 9.618612 msecs
Elapsed time: 8294.234684 msecs (is update-in that slow?)
Elapsed time: 4.223093 msecs by a-webb
Elapsed time: 8.166612 msecs
Elapsed time: 0.046654 msecs by andrew-myers (it is executed lazy right!?)
Run Code Online (Sandbox Code Playgroud)
使用core.matrix,该submatrix功能将完全符合您的要求:
(submatrix A 0 2 0 2)
=> #<NDWrapper [[1 2] [5 6]]>
Run Code Online (Sandbox Code Playgroud)
注意:NDWrapper它只是一个轻量级视图对象,可以索引到原始数组中.之所以这样做是因为它的内存效率更高,尽管对于像这样的小型矩阵来说这不太重要.
如果你想把四个季度作为一个序列,只需做类似的事情:
(for [[i j] [[0 0] [0 2] [2 0] [2 2]]]
(submatrix A i 2 j 2))
Run Code Online (Sandbox Code Playgroud)
你的助手改名为:
(defn vec-split-at [idx v] [(subvec v 0 idx) (subvec v idx)])
Run Code Online (Sandbox Code Playgroud)
使用助手分区矩阵:
(defn partition-matrix-at [m row col]
(mapcat (partial apply map vector)
(vec-split-at row (mapv (partial vec-split-at col) m))))
Run Code Online (Sandbox Code Playgroud)
A上面的示例:
(partition-matrix-at A 2 2)
=> ([[1 2]
[5 6]]
[[3 4]
[7 8]]
[[9 10]
[13 14]]
[[11 12]
[15 16]])
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
266 次 |
| 最近记录: |