(Lisp初学者) 我需要创建一个2D数组,并初始化数组中的每个单元格。使用基于前一单元格中的数据的函数初始化每个单元。因此,将使用函数的结果初始化作为0,1的单元格,该函数使用来自单元格0,0的数据,依此类推。
我想知道设置这样的数据结构的正确的clojure习惯用法是什么。
答案 0 :(得分:11)
阵列的表示实际上取决于您使用它的需要,而不是初始化它。例如,如果你有密集矩阵,你很可能应该使用这样的向量向量:
[[0, 1, 2, 3, 4],
[5, 6, 7, 8, 9],
[9, 8, 7, 6, 5],
[4, 3, 2, 1, 0],
[0, 1, 2, 3, 4]]
或单个向量,其中包含原始长度的其他信息:
{:length 5
:data
[0, 1, 2, 3, 4,
5, 6, 7, 8, 9,
9, 8, 7, 6, 5,
4, 3, 2, 1, 0,
0, 1, 2, 3, 4]
}
如果您需要稀疏矩阵,可以使用hash-map
s:
{0 {0 0, 4 4},
2 {2 7},
3 {0 4, 2 2}}
(因为您的2D阵列很小,并且您根据之前的数据生成下一个值,我相信第一个选项更适合您)。
如果要进行大量特定于矩阵的操作(乘法,分解等),您可能需要使用一些现有的库,如Incanter。
至于填写,我的提议是使用transients并存储中期结果,即(对于一维向量):
(defn make-array [initial-value f length]
(loop [result (transient []), length-left length, interim-value initial-value]
(if (= length-left 0)
(persistent! result)
(recur (conj! result (f interim-value)) (- length-left 1) (f interim-value))))
瞬态将避免在每个新元素上创建新的数据结构,并且临时值将避免从瞬态结构中读取前一个元素。
答案 1 :(得分:2)
我不知道这是不是一种糟糕的技术,但我已经使用散列(或通常是有序的)映射来指定2D“数组”。他们建立起来像这样:
{ [x y] value ... }
由于必须以某种方式指定数组的限制,因此存在缺点。与ffriend的帖子中描述的直接向量呈现相比,它可能非常慢。