Question

I'm trying to find out a way to create a copy of an array with switched rows and columns.
I want to do this by setting pointers from the shadow array to the original array so that item[2 1] points to item[1 2].

Using pointers will have the effect that when the original array is changed, the shadowed array will also reflect that change.

So far I came up with using displaced arrays of length 1 for every item in the array.
It works but the result is an array with array's.
My question is, is there a better way to do this?
And is there a way to use setf through the shadow array to set values in the original array?

My code so far:

(defun shadow-column-array (array)
  (let* ((colsize (second (array-dimensions array)))
         (rowsize (first (array-dimensions array)))
         (b (make-array (list colsize rowsize))))
    (dotimes (i rowsize b) 
      (dotimes (j colsize)

        (setf (aref b j i)
              (make-array 1 
                          :displaced-to array 
                          :displaced-index-offset (+ (* i rowsize) j)))))))

some output:

*a* => #2A((0.0 0.1 0.2) (1.0 1.1 1.2) (2.0 2.1 2.2))  

(setq b (shadow-column-array (*a*))  

*b* => #2A((#(0.0) #(1.0) #(2.0)) (#(0.1) #(1.1) #(2.1)) (#(0.2) #(1.2) #(2.2)))  

displaced arrays of the columns are now

 col1 => #(#(0.0) #(1.0) #(2.0))    
 col2 => #(#(0.1) #(1.1) #(2.1))   
 col3 => #(#(0.2) #(1.2) #(2.2))

No correct solution

OTHER TIPS

Make every element of the original array a 'reference to a cell'. Then create a shadow array with the same cells but the elements reversed. Changing the value in a cell will change the array contents.

(defun make-celled-array (m n init)
  (let ((array (make-array (list m n))))
    (dotimes (i m)
      (dotimes (j n)
        (setf (aref array i j) (list init))))    ; (list init) makes a 'cell'
    array))
(defun celled-array-ref (array m n)
  (car (aref array m n)))
(defsetf celled-array-ref (array m n) (val)
  `(setf (car (aref ,array ,m ,n)) ,val))

(defun shadow-celled-array (ca)
  (let ((m (array-dimension ca 1))    ; swapped
        (n (array-dimension ca 0)))
    (let ((array (make-array (list m n))))
      (dotimes (i m)
        (dotimes (j n)
          (setf (aref array i j) (aref ca j i))))   ; swapped
      array)))

Use:

* (defvar a1 (make-celled-array 2 4 1))
A1

* (setf (celled-array-ref a1 0 3) 10)
10

* a1
#2A(((1) (1) (1) (10)) ((1) (1) (1) (1)))

* (defvar a2 (shadow-celled-array a1))
A2

* a2
#2A(((1) (1)) ((1) (1)) ((1) (1)) ((10) (1)))

* (celled-array-ref a2 3 0)
10

* (setf (celled-array-ref a2 3 0) 100)
100

* (celled-array-ref a1 0 3)
100

I would maybe use two arrays and set both when I change the contents. You can write a SETF function for that easily. If it should look like a single data structure for the user, I would also use a CLOS instance with slots for the array.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top