From: AJ Rossini
Subject: "transposing" list of lists
Date: 
Message-ID: <1138346281.959047.274910@f14g2000cwb.googlegroups.com>
I'm playing around with data structures and in the process of
evaluating variations on the "matrix" theme as part of relearning lisp,
have been trying to "transpose" lists of lists.

By this I mean,  I'd like '('(A B C) '(1 2 3) '(E F H) '(4 5 6))
to become '( '(A 1 E 4) '(B 2 F 5) '(C 3 G 6))

Now it's clear that
  (mapcar #'list '(A B C) '(1 2 3) '(E F H) '(4 5 6))

gives me exactly what I want, but

(setf testlist '( '(A 1 E 4) '(B 2 F 5) '(C 3 G 6)))
(mapcar #'list testlist)

isn't it.  I was thinking that there must be some means to unwrap the
parens around the lisp, perhaps by (values testlist) or (values-list
testlist), but this still doesn't do the right thing.

I've checked both CLTL and PCL, but I'm still missing something
fundamental, obviously.  What am I missing?

(the underlying application behind all this is to evaluate data
structures which provide an equivalence for R's (S's) data.frame, i.e
statistical observations in rows, and typed-variables (discrete,
ordinal, categorical, other restrictions) in columns, i.e. standard
"cases-by-variables" format).  The other ideas I've had are a bit
easier, but there are other reasons for thinking about the
lists-of-lists approach.

From: Martin Svenson
Subject: Re: "transposing" list of lists
Date: 
Message-ID: <1138351445.946951.247880@f14g2000cwb.googlegroups.com>
Try (apply #'mapcar #'list testlist)

// Martin

AJ Rossini wrote:
>
> (setf testlist '( '(A 1 E 4) '(B 2 F 5) '(C 3 G 6)))
> (mapcar #'list testlist)
> 
> isn't it.
From: Peder O. Klingenberg
Subject: Re: "transposing" list of lists
Date: 
Message-ID: <ks4q3qqc8p.fsf@beto.netfonds.no>
"AJ Rossini" <··········@gmail.com> writes:

> What am I missing?

Apply.

CL-USER> (defparameter *matrix* '((a b c) (d e f) (g h i)))
*MATRIX*
CL-USER> (apply #'mapcar #'list *matrix*)
((A D G) (B E H) (C F I))

But this idiom, while cute, is not a good function for transposing
matrices.  There was a longish discussion about this in this forum a
while ago, but I'm too lazy to google for it.  The upshot is that
you're likely to run afould of CALL-ARGUMENTS-LIMIT if you have
decent-sized matrices.

You're probably better off with one of the dedicated matrix packages
out there, which I'm sure you can find pointers to on
<http://www.cliki.net/> or google.

...Peder...
-- 
Sl�v uten dop.
From: Pascal Bourguignon
Subject: Re: "transposing" list of lists
Date: 
Message-ID: <87k6cmvwze.fsf@thalassa.informatimago.com>
"AJ Rossini" <··········@gmail.com> writes:

> I'm playing around with data structures and in the process of
> evaluating variations on the "matrix" theme as part of relearning lisp,
> have been trying to "transpose" lists of lists.
>
> By this I mean,  I'd like '('(A B C) '(1 2 3) '(E F H) '(4 5 6))
> to become '( '(A 1 E 4) '(B 2 F 5) '(C 3 G 6))

Remember that 'x === (quote x)

 '('(A B C) '(1 2 3) '(E F H) '(4 5 6))
== (quote ((quote (A B C)) (quote (1 2 3)) (quote (E F H)) (quote (4 5 6))))
When you evaluate this expression, you get the following list:

  ((quote (A B C)) (quote (1 2 3)) (quote (E F H)) (quote (4 5 6)))

That is, you have a 4x2 matrix in which the first row contains only
the symbol QUOTE.

Perhaps that's what you want, perhaps not...


> Now it's clear that
>   (mapcar #'list '(A B C) '(1 2 3) '(E F H) '(4 5 6))
>
> gives me exactly what I want, but
>
> (setf testlist '( '(A 1 E 4) '(B 2 F 5) '(C 3 G 6)))
> (mapcar #'list testlist)
>
> isn't it.  I was thinking that there must be some means to unwrap the
> parens around the lisp, perhaps by (values testlist) or (values-list
> testlist), but this still doesn't do the right thing.

APPLY is what you need.


-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

ATTENTION: Despite any other listing of product contents found
herein, the consumer is advised that, in actuality, this product
consists of 99.9999999999% empty space.
From: AJ Rossini
Subject: Re: "transposing" list of lists
Date: 
Message-ID: <1138363118.732355.171030@g14g2000cwa.googlegroups.com>
Thanks to all that not only mentioned apply (which I knew about) but
how to use it properly (which I had never known about).   Also, the
reminder of argument limits is well taken.  Finally, Pascal points out
a silly error/confusion that I keep on making, despite my best
intentions.

For those that suggested other approaches, yes, I've been going through
MatLisp, FEMlisp, and Nlisp recently, and they are all part of the
general solution -- however, it's not really numerical matrices that I
need, but matrices whose columns (or rows, when transformed) are of a
specifiable, flexible, to be assigned (and changed) types.  These go
through an appropriate transformation into a numerical matrix, whose
increased dimensions depend on the statistical model to be fit).

(since I'm just playing with data structures, all are fair play as long
as I write the appropriate translators, of which the list-of-list
transposer was a missing piece -- isn't Lisp great!).

Thanks again!


Pascal Bourguignon wrote:
> "AJ Rossini" <··········@gmail.com> writes:
>
> > I'm playing around with data structures and in the process of
> > evaluating variations on the "matrix" theme as part of relearning lisp,
> > have been trying to "transpose" lists of lists.
> >
> > By this I mean,  I'd like '('(A B C) '(1 2 3) '(E F H) '(4 5 6))
> > to become '( '(A 1 E 4) '(B 2 F 5) '(C 3 G 6))
>
> Remember that 'x === (quote x)
>
>  '('(A B C) '(1 2 3) '(E F H) '(4 5 6))
> == (quote ((quote (A B C)) (quote (1 2 3)) (quote (E F H)) (quote (4 5 6))))
> When you evaluate this expression, you get the following list:
>
>   ((quote (A B C)) (quote (1 2 3)) (quote (E F H)) (quote (4 5 6)))
>
> That is, you have a 4x2 matrix in which the first row contains only
> the symbol QUOTE.
>
> Perhaps that's what you want, perhaps not...
>
>
> > Now it's clear that
> >   (mapcar #'list '(A B C) '(1 2 3) '(E F H) '(4 5 6))
> >
> > gives me exactly what I want, but
> >
> > (setf testlist '( '(A 1 E 4) '(B 2 F 5) '(C 3 G 6)))
> > (mapcar #'list testlist)
> >
> > isn't it.  I was thinking that there must be some means to unwrap the
> > parens around the lisp, perhaps by (values testlist) or (values-list
> > testlist), but this still doesn't do the right thing.
>
> APPLY is what you need.
>
>
> --
> __Pascal Bourguignon__                     http://www.informatimago.com/
>
> ATTENTION: Despite any other listing of product contents found
> herein, the consumer is advised that, in actuality, this product
> consists of 99.9999999999% empty space.
From: Pascal Bourguignon
Subject: Re: "transposing" list of lists
Date: 
Message-ID: <87r76tvovw.fsf@thalassa.informatimago.com>
"AJ Rossini" <··········@gmail.com> writes:

> Thanks to all that not only mentioned apply (which I knew about) but
> how to use it properly (which I had never known about).   Also, the
> reminder of argument limits is well taken.  Finally, Pascal points out
> a silly error/confusion that I keep on making, despite my best
> intentions.
>
> For those that suggested other approaches, yes, I've been going through
> MatLisp, FEMlisp, and Nlisp recently, and they are all part of the
> general solution -- however, it's not really numerical matrices that I
> need, but matrices whose columns (or rows, when transformed) are of a
> specifiable, flexible, to be assigned (and changed) types.  These go
> through an appropriate transformation into a numerical matrix, whose
> increased dimensions depend on the statistical model to be fit).
>
> (since I'm just playing with data structures, all are fair play as long
> as I write the appropriate translators, of which the list-of-list
> transposer was a missing piece -- isn't Lisp great!).

Ah but LISP = List & Intelligent SYMBOLIC Processing.
You can put any symbolic expressions in arrays as well as in lists:

(defun transpose (matrix)
  (let ((transposed (make-array (nreverse (array-dimensions matrix))
                                :element-type (array-element-type matrix))))
    (loop :for i :from 0 :below (array-dimension matrix 0) :do
       (loop :for j :from 0 :below (array-dimension matrix 1) :do
          (setf (aref transposed j i) (aref matrix i j))))
    transposed))


(transpose #2A((1 2 3) ("one" "two" "tree") (un deux trois)
               (() (()) ((()))) (#(1) #(2 2) #(3 3 3))))
--> 
#2A((1 "one" UN NIL #(1))
    (2 "two" DEUX (NIL) #(2 2))
    (3 "tree" TROIS ((NIL)) #(3 3 3)))


(transpose (make-array '(2 4) :element-type 'fixnum
                :initial-contents '((11 12 13 14)(21 22 23 24))))
-->
#2A((11 21) (12 22) (13 23) (14 24))


-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

THIS IS A 100% MATTER PRODUCT: In the unlikely event that this
merchandise should contact antimatter in any form, a catastrophic
explosion will result.
From: AJ Rossini
Subject: Re: "transposing" list of lists
Date: 
Message-ID: <1138365010.994480.91630@g43g2000cwa.googlegroups.com>
Exactly!