Page 1 of 2
Print the contents of a multi-dimensional array
Posted: Wed Jul 27, 2011 7:52 am
by I X Code X 1
Hello,
I am trying to print the contents of an Array of rank 2. However, I am getting this error:
Code: Select all
; At the moment it would just print a bunch of nils, but that's fine for the moment.
CG-USER(15): (defparameter *hi* (make-array '(5 5)))
*HI*
CG-USER(16): *hi*
#2A((NIL NIL NIL NIL NIL)
(NIL NIL NIL NIL NIL)
(NIL NIL NIL NIL NIL)
(NIL NIL NIL NIL NIL)
(NIL NIL NIL NIL NIL))
CG-USER(17): (loop for i across *hi* do (print i))
Error: attempt to take the length of a non-sequence:
#<Array of rank 2 @ #x2122e832>
I know this of course would work if it was just a vector (one-dimension), but does Common Lisp have any method of printing the contents of a multi-dimensional array?
Thanks!
Re: Print the contents of a multi-dimensional array
Posted: Wed Jul 27, 2011 8:16 am
by ramarren
I'm not sure what you are asking. You can see the printed form of a multi-dimensional arrays right in your code example. Just use PRINT directly on an array. If you mean to print in a table form then just use a nested loop and iterate by indices.
Re: Print the contents of a multi-dimensional array
Posted: Wed Jul 27, 2011 9:21 am
by I X Code X 1
Thanks,
I guess I was not aware you could just use PRINT directly on the array. Though that's not what I wanted. I want to print each row of the array as such
Code: Select all
; For the above I would want it to come out like this:
nil nil nil nil nil
nil nil nil nil nil
nil nil nil nil nil
nil nil nil nil nil
nil nil nil nil nil
; without the array marks, #2A(...)
Just not sure how to get at each individual row of the array.
EDIT: Alright, I think I understand how to do this now. Will need to do the nested loop as Ramarren posted. Thanks.
Re: Print the contents of a multi-dimensional array
Posted: Wed Jul 27, 2011 9:45 am
by I X Code X 1
Code: Select all
(loop for i from 0 to 4 do
(loop for m from 0 to 4 collect (aref *hi* i m)))
This is returning NIL and not quite sure why.
Just using collect to see if I can figure this out.
Re: Print the contents of a multi-dimensional array
Posted: Wed Jul 27, 2011 9:47 am
by ramarren
I X Code X 1 wrote:This is returning NIL and not quite sure why.
The outer loop doesn't care about COLLECT in the inner loop. The outer loop has no clause which would cause a return value.
Re: Print the contents of a multi-dimensional array
Posted: Wed Jul 27, 2011 9:59 am
by I X Code X 1
Ah yeah, I kinda knew that was the reason. Just didn't want it to be. Anyway though, I got it to do what I wanted it to. Might not be the best way, but it works:
Code: Select all
(loop for i from 0 to 4 do
(format t "~a~&" (loop for m from 0 to 4 do
(format t "~a" (aref *hi* i m)))))
NILNILNILNILNILNIL
NILNILNILNILNILNIL
NILNILNILNILNILNIL
NILNILNILNILNILNIL
NILNILNILNILNILNIL
Tried it with PRINT's and PRINC's, but the fact that it returns a NIL each time makes it look bad. Anyway to get it out of there? FORMAT only returns the NIL at the very end, which is nice.
Code: Select all
(loop for i from 0 to 4 do
(print (loop for m from 0 to 4 do
(princ (aref *hi* i m)))))
NILNILNILNILNIL
NIL NILNILNILNILNIL
NIL NILNILNILNILNIL
NIL NILNILNILNILNIL
NIL NILNILNILNILNIL
NIL
NIL
EDIT: I made it a bit better, looks like I really only need the first FORMAT call. Can use princ after that.
Code: Select all
(loop for i from 0 to 4 do
(format t "~a~&" (loop for m from 0 to 4 do
(princ (aref *hi* i m)))))
NILNILNILNILNILNIL
NILNILNILNILNILNIL
NILNILNILNILNILNIL
NILNILNILNILNILNIL
NILNILNILNILNILNIL
Thanks for the help!
Re: Print the contents of a multi-dimensional array
Posted: Wed Jul 27, 2011 10:14 am
by ramarren
I X Code X 1 wrote:Ah yeah, I kinda knew that was the reason. Just didn't want it to be.
That is only one of many reasons I prefer iterate, which provides
this exact feature. Unless the code walker somehow gets tangled.
Why do you have a printing operation in the outer loop? If I wanted to print an array I would do something like this:
Code: Select all
(defun print-2d-array-as-table (array)
(loop for i from 0 below (array-dimension array 0)
do (loop for j from 0 below (array-dimension array 1)
do (princ (aref array i j))
(if (= j (1- (array-dimension array 1)))
(terpri)
(princ #\Space)))))
Re: Print the contents of a multi-dimensional array
Posted: Wed Jul 27, 2011 10:22 am
by I X Code X 1
Thanks, Ramarren!
I actually wasn't aware of ARRAY-DIMENSION. Iterate does look more appealing, definitely with the link you posted.
Re: Print the contents of a multi-dimensional array
Posted: Wed Jul 27, 2011 4:42 pm
by I X Code X 1
This is what I was working on. Credit for the print-array function goes to Ramarren. Thanks for the help!
I just made a simple string generator. I work for a company and have to do a lot of QA-type things and one thing that I had to do the other day was to verify that text fields only allow the specified amount of characters. Got a little bit annoying to type it all out, even with copy and paste. So today on my down time I threw this together. Asks you for how many characters and how many lines you would like to have:
Code: Select all
(defun string-generator ()
(format t "Please enter the amount of characters: ")
(let ((c (read)))
(format t "~&Please enter the amount of lines: ")
(let* ((l (read))
(a (make-array `(,l ,c))))
(map-into (make-array (reduce '* (array-dimensions a))
:element-type
(array-element-type a) :displaced-to a)
(lambda () (random 10)))
(print-array a))))
(defun print-array (array)
(loop for i from 0 below (array-dimension array 0)
do (loop for j from 0 below (array-dimension array 1)
do (princ (aref array i j))
(if (= j (1- (array-dimension array 1)))
(terpri)))))
CG-USER(68): (string-generator)
Please enter the amount of characters: 20
Please enter the amount of lines: 20
56492889241784419519
12366116046700017433
02054109384718440791
53637470891442215430
37343259400359346410
26368560619707029259
41110582820691777328
59418319708063574168
96121143614027244294
08906379198745003444
05548522896607317289
30782460306116910908
73283493220236328021
39384296821902656149
34239764840990097742
38536812464963755711
48749151276399492348
03995008638774135280
10943530499981882575
23618230850678623681
NIL
This isn't that complex or anything, but taught me a lot about arrays in Common Lisp. Any tips to make it better or things that I should have done differently is appreciated.
Re: Print the contents of a multi-dimensional array
Posted: Wed Jul 27, 2011 5:15 pm
by Paul
Ramarren wrote:That is only one of many reasons I prefer iterate, which provides
this exact feature. Unless the code walker somehow gets tangled.
(loop named <name> ...)
FWIW, you don't need two loops:
Code: Select all
(defun print-2d-array-as-table (array)
(loop for i below (array-total-size array) do
(if (zerop (mod i (array-dimension array 0)))
(terpri)
(princ #\Space))
(princ (row-major-aref array i))))