Swapping the rows and columns in a two dimensional array

  • Thread starter Suresh Jeevanandam
  • Start date
S

Suresh Jeevanandam

Guest
In skill, I have a two dimensional array, and I want to swap the rows
and columns. Below is something I could come up. But I think there
should some other simpler and better way. Your suggestion is welcome.

procedure(lrange(num)
;return a list of numbers from 1 to num
let((rlist)
rlist = nil
while(num > 0
rlist = cons(num rlist)
num = num-1
)
rlist
))

procedure(swapRowCol(aList)
;Swap the columns and rows in a two dimensional array
mapcar(
lambda( (num)
mapcar(
lambda( (row)
nthelem(num row)
)
aList
)
)
lrange(length(aList))
)
)

regards,
Suresh
 
Suresh,

First of all, PLEASE do not get lists mixed up with arrays. Lists in SKILL are
not the same as arrays, and thinking of them as equivalent tends to lead to very
inefficient programs.

Why are they different? Well, an array is random access; you can specify an
index of an array, and the address of the location can be directly computed.
Lists however are sequential; if you specify an index, then that location is
found by starting at the beginning of the list and hopping along until you reach
that index.

As a result, using functions like nth and nthelem are very slow for large lists,
especially when executed in a loop, as they have to start from the beginning
each time.

Anyway, it sounds as if what you are trying to do is to transpose a list of
lists. Your code does this, but rather inefficiently, and only for square lists
of lists (i.e. the length of the list is the same as the length of each
sublist).

Compare it with my implementation:

procedure(abSwapRowCol(aList)
apply('mapcar cons('list aList))
)

Which is:

a) shorter (by some way ;-> )
b) more efficient
c) quite elegant (even if I do say so myself)
d) handles non-square lists of lists.

Try:

a='((1 2 3 4 5) (6 7 8 9 10))
b='((1 2 3 4) (5 6 7 8) (9 10 11 12) (13 14 15 16))

and then do abSwapRowCol() on both of threse.

Regards,

Andrew.

On Wed, 04 Aug 2004 17:47:16 +0530, Suresh Jeevanandam
<sureshjeeva@DELETETHISindia.ti.com> wrote:

In skill, I have a two dimensional array, and I want to swap the rows
and columns. Below is something I could come up. But I think there
should some other simpler and better way. Your suggestion is welcome.

procedure(lrange(num)
;return a list of numbers from 1 to num
let((rlist)
rlist = nil
while(num > 0
rlist = cons(num rlist)
num = num-1
)
rlist
))

procedure(swapRowCol(aList)
;Swap the columns and rows in a two dimensional array
mapcar(
lambda( (num)
mapcar(
lambda( (row)
nthelem(num row)
)
aList
)
)
lrange(length(aList))
)
)

regards,
Suresh
--
Andrew Beckett
Senior Technical Leader
Custom IC Solutions
Cadence Design Systems Ltd
 
For those who (like me ) need a little head scratching to undertand
Andrew's lisp hacks:
abSwapRowCol( '((1 2) (3 4)) )
<->
mapcar( 'list '(1 2) '(3 4) )

what happens with non-square lists is murky to me, but it seems mapcar
simply truncates numrows to length of the smallest sublist. i.e.
abSwapRowCol( '((1 2) (3 4 5)) )
returns 2 rows.

Andrew Beckett wrote:
Suresh,

First of all, PLEASE do not get lists mixed up with arrays. Lists in SKILL are
not the same as arrays, and thinking of them as equivalent tends to lead to very
inefficient programs.

Why are they different? Well, an array is random access; you can specify an
index of an array, and the address of the location can be directly computed.
Lists however are sequential; if you specify an index, then that location is
found by starting at the beginning of the list and hopping along until you reach
that index.

As a result, using functions like nth and nthelem are very slow for large lists,
especially when executed in a loop, as they have to start from the beginning
each time.

Anyway, it sounds as if what you are trying to do is to transpose a list of
lists. Your code does this, but rather inefficiently, and only for square lists
of lists (i.e. the length of the list is the same as the length of each
sublist).

Compare it with my implementation:

procedure(abSwapRowCol(aList)
apply('mapcar cons('list aList))
)

Which is:

a) shorter (by some way ;-> )
b) more efficient
c) quite elegant (even if I do say so myself)
d) handles non-square lists of lists.

Try:

a='((1 2 3 4 5) (6 7 8 9 10))
b='((1 2 3 4) (5 6 7 8) (9 10 11 12) (13 14 15 16))

and then do abSwapRowCol() on both of threse.

Regards,

Andrew.

On Wed, 04 Aug 2004 17:47:16 +0530, Suresh Jeevanandam
sureshjeeva@DELETETHISindia.ti.com> wrote:


In skill, I have a two dimensional array, and I want to swap the rows
and columns. Below is something I could come up. But I think there
should some other simpler and better way. Your suggestion is welcome.

procedure(lrange(num)
;return a list of numbers from 1 to num
let((rlist)
rlist = nil
while(num > 0
rlist = cons(num rlist)
num = num-1
)
rlist
))

procedure(swapRowCol(aList)
;Swap the columns and rows in a two dimensional array
mapcar(
lambda( (num)
mapcar(
lambda( (row)
nthelem(num row)
)
aList
)
)
lrange(length(aList))
)
)

regards,
Suresh


--
Andrew Beckett
Senior Technical Leader
Custom IC Solutions
Cadence Design Systems Ltd
 
On Thu, 05 Aug 2004 00:28:29 -0400, oghdayan <oghdayan_AT@xs4all_dot.nl> wrote:

For those who (like me ) need a little head scratching to undertand
Andrew's lisp hacks:
abSwapRowCol( '((1 2) (3 4)) )
-
mapcar( 'list '(1 2) '(3 4) )
Indeed. I should have explained that, but it was getting late last night...
If you have abSwapRowCol('((1 2) (3 4) (5 6) (7 8)) this ends up
as mapcar('list '(1 2) '(3 4) '(5 6) '(7 8)). mapcar is passed the name of a
function as the first argument, and then it processes each of the lists in the
argument list to mapcar in parallel, passing the first element of each list as
all the arguments to the list() function, and then moving on to the second
elements, and so on.

what happens with non-square lists is murky to me, but it seems mapcar
simply truncates numrows to length of the smallest sublist. i.e.
abSwapRowCol( '((1 2) (3 4 5)) )
returns 2 rows.
That's a non-rectangular list, not a non-square list. By non-square I meant one
which had all the sub-lists the same length as each other, but the sub-list
length being different from the number of sub-lists. Suresh's code didn't work
with that.

However, my code will not necessarily work with non-rectangular lists (and if
you think about it, what would you want it to do). When mapcar is presented with
multiple lists, they need really to be the same length, but it will cope
provided that the first list is the shortest. If the first list is not the
shortest, it will error:

*Error* mapcar: multiple arg lists should be the same length

If the lists are uneven, and the first is the shortest (or equal shortest), then
it will truncate each list to the length of the first.

However, I think that the expectation here is that these list-of-lists would be
properly constructed. You could always add a simple check for the lengths being
equal first if you really wanted:

let(((len length(car(aList))))
forall(elem cdr(aList) len==length(elem))
)

but of course this slows it down a little if you know your list of lists is
properly constructed.

Regards,

Andrew.

--
Andrew Beckett
Senior Technical Leader
Custom IC Solutions
Cadence Design Systems Ltd
 
"Suresh" == Suresh Jeevanandam <sureshjeeva@DELETETHISindia.ti.com> writes:
Suresh> In skill, I have a two dimensional array, and I want to
Suresh> swap the rows and columns. Below is something I could come
Suresh> up. But I think there should some other simpler and better
Suresh> way. Your suggestion is welcome.

Suresh> procedure(lrange(num) ;return a list of numbers from 1
Suresh> to num let((rlist) rlist = nil while(num > 0 rlist =
Suresh> cons(num rlist) num = num-1 ) rlist ))

Suresh> procedure(swapRowCol(aList) ;Swap the columns and rows
Suresh> in a two dimensional array mapcar( lambda( (num) mapcar(
Suresh> lambda( (row) nthelem(num row) ) aList ) )
Suresh> lrange(length(aList)) ) )

Suresh> regards, Suresh

If I understood correctly you are trying to do a transpose of a matrix
that is represented as a list of lists, each sublist being a row of
the matrix.

The easiest way to do a transpose in this case is
(apply 'mapcar 'list matrix)
where matrix looks something like '((1 2 3) (4 5 6))

Satya

--
Remove XXX and YYY to get my address
 

Welcome to EDABoard.com

Sponsor

Back
Top