Page 1 of 1

Access a specific row from an array

Posted: Wed Apr 22, 2009 11:27 am
by Ferreira
Is there any way I can access a specific row from an array, i.e., I have this array:

#2A((1 2) (3 4))

How can I get the first row as #A(1 2)?

Thanks in advance.

Re: Access a specific row from an array

Posted: Wed Apr 22, 2009 12:35 pm
by gugamilare
Unfortunately, I believe the only way to do this explicitly is to create a fresh vector and copy over the elements of that row. You can also do this implictly using closures:

Code: Select all

(defun nth-row (array index)
  (lambda (col)
    (aref array index col)))
And

Code: Select all

(let* ((array #2A((1 2) (3 4)))
       (row-0 (nth-row array 0)))
  (dotimes (i 2)
    (print (funcall row-0 i))))
And, if you want to be able to change the value

Code: Select all

(defun nth-row (array index)
  (lambda (col &optional new-val)
    (if new-val
      (setf (aref array index col) new-val)
      (aref array index col))))

Re: Access a specific row from an array

Posted: Wed Apr 22, 2009 1:07 pm
by ramarren
See documentation on make-array, in particular :displaced-to and :displaced-index-offset, for example:

Code: Select all

CL-USER> (defparameter *a* (make-array (list 2 2) :initial-contents '((1 2)(3 4))))
*A*
CL-USER> (make-array 2 :displaced-to *a*)
#(1 2)
CL-USER> (make-array 2 :displaced-to *a* :displaced-index-offset 1)
#(2 3)
CL-USER> (make-array 2 :displaced-to *a* :displaced-index-offset 2)
#(3 4)
Note that due to how arrays are laid out in memory this can only be used to access rows or parts of rows, and not columns.

There is also affine indexing library, which might be used for similar purposes.

Re: Access a specific row from an array

Posted: Wed Apr 22, 2009 1:21 pm
by Ferreira
Thanks, make-array's keyworded parameters solved my problem.

;)

Re: Access a specific row from an array

Posted: Wed Apr 22, 2009 2:07 pm
by gugamilare
Ramarren wrote:See documentation on make-array, in particular :displaced-to and :displaced-index-offset, for example:

Code: Select all

CL-USER> (defparameter *a* (make-array (list 2 2) :initial-contents '((1 2)(3 4))))
*A*
CL-USER> (make-array 2 :displaced-to *a*)
#(1 2)
CL-USER> (make-array 2 :displaced-to *a* :displaced-index-offset 1)
#(2 3)
CL-USER> (make-array 2 :displaced-to *a* :displaced-index-offset 2)
#(3 4)
Note that due to how arrays are laid out in memory this can only be used to access rows or parts of rows, and not columns.

There is also affine indexing library, which might be used for similar purposes.
Hum, my bad, I didn't think about this. Oftenly I use displaced arrays to turn multidimentional arrays into one-dimensional, or to make a destructive version of subseq.

But this doesn't work with columns, and my version can be easily addapted :)