arrays - 如何使用 make-array 或 coerce 将列表转换为具有相同输出的 Common Lisp 中的一维数组(向量)?

标签 arrays list vector common-lisp

我想从一个简单的列表转换:

'(1 2 3)

到一维数组(向量):

#(1 2 3)

我找到了 this question这很相似,但没有涵盖这个问题。

我也设法找到了实现它的方法。不确定它是否是最好的:

CL-USER> (coerce '(1 2 3) 'vector)
#(1 2 3)
CL-USER> (type-of *)
(SIMPLE-VECTOR 3)

我想知道是否可以使用 make-array 来获得相同的结果。我试过:


CL-USER> (make-array '() :initial-contents '(1 2 3)) 
#0A(1 2 3)
CL-USER> (type-of *)
(SIMPLE-ARRAY T NIL)

这很接近,但我不明白 #0A(1 2 3) 中的 #0A

出于某种我不明白的原因,此输出不适用于进一步的组合,例如 aref:

CL-USER> (aref #0A(1 2 3) 0)
; Evaluation aborted on #<SIMPLE-ERROR "Wrong number of subscripts, ~W, for array of rank ~W." {1003C07793}>.

是否可以使用make-array 来实现与coerce 相同的结果? 这两种方法有什么区别? 其中一个比另一个更快还是更优雅?

最佳答案

COERCE很好,您甚至可以根据需要指定元素类型:

USER> (coerce '(1 2 3) '(vector fixnum))
#(1 2 3)
USER> (describe *)
#(1 2 3)
  [simple specialized vector]

Element-type: FIXNUM
Length: 3

您可以对 make-array 执行相同的操作,但您需要提供正确的维度。维度参数表示可能的多维数组有多少行、多少列等。它应该是一个列表,但是当你只有一个维度时,它可以只是一个数字。这里的两种形式是等价的:

USER> (make-array 3 :initial-contents '(1 2 3))
#(1 2 3)

USER> (make-array '(3) :initial-contents '(1 2 3))
#(1 2 3)

通常你会调用(length list) .与 coerce 相比的附加值是你可以指定 :fill-pointer:adjustable参数,coerce 的类型参数无法传达。

数组的打印表示是 #nA() , 其中n是数组的维数,其中数字和A如果它是向量 (n = 1),则省略。例如:

USER> (make-array '(10 2) :initial-element 0)
#2A((0 0) (0 0) (0 0) (0 0) (0 0) (0 0) (0 0) (0 0) (0 0) (0 0))

对于给定的维度数组 n ,您可以使用 aref 访问元素以及与维度一样多的参数,以行优先顺序(与您在 make-array 中指定维度的顺序相同)。

USER> (aref * 5 1)
0 (0 bits, #x0, #o0, #b0)

在您的示例中,您定义了一个维度为 0 的数组,因为您写了 '() (也就是 ()nil )作为维度。如果您需要一个盒子来存储单个元素,则可以使用此方法:

USER> (defparameter *box* (make-array nil :element-type '(mod 8)))
*BOX*
USER> (describe *box*)
#0A0
  [simple specialized array]

Element-type: (UNSIGNED-BYTE 4)
Dimensions: NIL
Storage vector: #<(SIMPLE-ARRAY (UNSIGNED-BYTE 4) (1)) {101EA0C59F}>
; No values

USER> (setf (aref *box*) 7)
7 (3 bits, #x7, #o7, #b111)

USER> (incf (aref *box*))
8 (4 bits, #x8, #o10, #b1000)

USER> (aref *box*)
8 (4 bits, #x8, #o10, #b1000)

(如您所见,数组中可以存储的值是对应于upgraded-element-type的值,这里是(unsigned-byte 4);例如(setf (aref *box*) (expt 2 16))表示错误)

看起来像:initial-contents结果与 :initial-element 相同,因为在您的示例中,零维数组的内容是列表 (1 2 3)

Is one of them faster or more elegant than the other?

我尝试使用 coerce如果可能的话,因为它写起来更短,而且看起来更能描述我正在做的事情。我不认为它更快,除非您事先知道列表的长度。

关于arrays - 如何使用 make-array 或 coerce 将列表转换为具有相同输出的 Common Lisp 中的一维数组(向量)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68833134/

相关文章:

java - 按值复制 Java 列表

c++ - 将 vector 分配给多重集

java - 相邻数组的最小值

ios - Swift 类函数在 for-in 循环后返回空

string - 查找列表中最长项目长度的最有效方法是什么?

c++ - 访问/填充来自不同类的 vector ?

c++ - 带有索引和迭代器的 vector

arrays - Swift 从具有不同索引的其他字典数组中获取值

arrays - 在字典中添加键值对 swift

list - 键入要求非空列表的最佳方式是什么(不使用 Scalaz)?