如何转换列表到一个一维数组(向量)在公共Lisp有相同的输出使用make-array或强制?



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

'(1 2 3)

指向一维数组(vector):

#(1 2 3)

我发现了一个类似的问题,但没有涵盖这个问题。

我也设法找到了实现它的方法。不知道这是不是最好的:

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做同样的事情,但是你需要给正确的维度。dimension参数指示可能的多维数组有多少行、多少列等。它应该是一个列表,但是当你只有一维的时候,它可以是一个数字。这里的两种形式都是等价的:

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是数组的维数,如果是向量(n = 1),则省略数字和A。例如:

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的给定数组,按照row-major的顺序(与您在make-array中指定维度的顺序相同),使用aref和尽可能多的参数访问元素。

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)

其中一个比另一个更快或更优雅吗?

我尽量使用coerce,因为它写得更短,它看起来更能描述我正在做的事情。我不认为它更快,除非你事先知道列表的长度。

最新更新