Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

How to do multi-dimensional arrays?

3 views
Skip to first unread message

Steven D. Majewski

unread,
Jan 19, 1995, 11:39:55 AM1/19/95
to

>
> >While I'm at it, is there a elegant way to remove the first
> >element of a list?
>
> Is this elegant enough?
> >>> xxx = [4,2,8,5,9]
> >>> yyy = xxx[0]; xxx=xxx[1:]
> >>> print yyy, xxx
> 4 [2, 8, 5, 9]
>

And if you don't need the removed value, there is also:
>>> xxx = [1,2,3,4,5]
>>> xxx
[1, 2, 3, 4, 5]
>>> del xxx[0]
>>> xxx
[2, 3, 4, 5]
>>>


Re: Multi-dimensional arrays:
I've used tuple-indexed dictionaries for sparse arrays.
For real homogeneous ( i.e. all integer or floating point )
arrays, you can wrap array module in a class that maps n-dim.
indexes into 1-dimensional indexes.


Note that for tuple-indexed dictionaries and tuple-indexed classes,
the syntax MUST be:

array[(i,j)]

and not:

array[i,j]

which is a syntax error.

When I have used this, I find remembering to wrap the naked tuple
into a single tuple arg a source of mistakes. Is there a reason
why we couldn't relax the syntax here some way ?

I haven't looke at the grammer here, but I assume it's a precedence
problem. Unwrapped tuples are valid in many places, and indexing
does have a different syntax than function call, so I don't think
there is an ambiguity problem with the rule that whatever is inside
"[" ... "]" is a single argument. i.e.

array[i,j] == array[(i,j)]

both notations would be equivalent and might both be dispatched to:

__getitem__( self, index )
i,j = index
...

---| Steven D. Majewski (804-982-0831) <sd...@Virginia.EDU> |---
---| Computer Systems Engineer University of Virginia |---
---| Department of Molecular Physiology and Biological Physics |---
---| Box 449 Health Science Center Charlottesville,VA 22908 |---

Guido.va...@cwi.nl

unread,
Jan 20, 1995, 8:42:28 AM1/20/95
to
> Note that for tuple-indexed dictionaries and tuple-indexed classes,
> the syntax MUST be:
>
> array[(i,j)]
>
> and not:
>
> array[i,j]
>
> which is a syntax error.

That's a good one. Quoting from the current syntax:

trailer: '(' [testlist] ')' | '[' subscript ']' | '.' NAME
subscript: test | [test] ':' [test]

I suppose this dates back to the times when the only subscriptable
objects were sequences (which always have integer indices) and
old-style dictionaries (which always had string keys).

This could be changed to

subscript: testlist | [testlist] ':' [testlist]

without problems (and without changing compile.c, even!).

Unfortunately my parser generator isn't powerful enough to let it be

subscript: testlist | [test] ':' [test]

(it would have to decide whether to go and parse a testlist or a test
based on the first symbol, and since a testlist begins with a test it
can't -- and unlile Yacc it can't decide later).

An alternative (which would require changing compile.c) would be to
leave subscript alone and change the definition of trailer to

trailer: '(' [testlist] ')' | '[' subscriptlist ']' | '.' NAME
subscriptlist: subscript (',' subscript)**

The difference would be the interpretation of expressions like

a[i:j,k]

-- while always illegal, grouping it like

a[(i:j), k]

makes more sense in the light of a possible future extension to
multi-dimensional slices than grouping it like

a[i : (j,k)]

As always, I'll leave it to a volunteer to experiment with this. Just
edit Grammar/Grammar and run the Parser/pgen script.

--Guido van Rossum, CWI, Amsterdam <mailto:Guido.va...@cwi.nl>
<http://www.cwi.nl/cwi/people/Guido.van.Rossum.html>

Steven D. Majewski

unread,
Jan 19, 1995, 7:59:32 PM1/19/95
to
On Thu, 19 Jan 1995, Aaron Watters wrote:

> The fix to avoid shared references is just a bit less elegant,
> but not too bad:
> >>> arr = [None]*4
> >>> for i in range(4): arr[i] = [0]*4
> ...
> >>> arr[1][2] = 42
> >>> arr
> [[0, 0, 0, 0], [0, 0, 42, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
> Yours, not feeling like working right now, -a.


OK. I'll call!
How about:

>>> arr = map( lambda x: [x]*4, [0]*4 )
>>> arr
[[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
>>> arr[1][2] = 42
>>> arr
[[0, 0, 0, 0], [0, 0, 42, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
>>>


Unfortunately, this doesn't appear to recursively propagate to
higher dimensions. :-(


>>> XXX = map( lambda x: [x]*4, map( lambda x: [x]*4, [0]*4 ) )
>>> XXX[1][2][3] = 123
>>> XXX
[[[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]], [[0, 0, 0, 123], [0,
0, 0, 123], [0, 0, 0, 123], [0, 0, 0, 123]], [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0,
0, 0], [0, 0, 0, 0]], [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]]

Aaron Watters

unread,
Jan 20, 1995, 9:49:27 AM1/20/95
to
Steve Majewski writes that a 2d array can be initialized without
shared reference problems thusly:

>arr = map( lambda x: [x]*4, [0]*4 )

but has problems with

>>>> XXX = map( lambda x: [x]*4, map( lambda x: [x]*4, [0]*4 ) )

which produces update anomalies:

>>> XXX[1][2][3] = 123
>>> XXX
[[[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]], [[0, 0, 0, 123], [0,
0, 0, 123], [0, 0, 0, 123], [0, 0, 0, 123]], [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0,
0, 0], [0, 0, 0, 0]], [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0,
0, 0, 0]]]

This can be fixed by putting one lambda inside the other, thusly:

>>> YYY = map((lambda x: (map(lambda y: [y]*4,[0]*4))),[0]*4)

where

>>> YYY[1][2][3] = 231

only changes the one entry, as expected.

==Non-masochists, please delete this article NOW =======

And for the functional programming freaks out there here is a
matrix multiplication function in native python that follows
the f.p. style (except for initializations, which could be omitted
if you really insist).

def mmultfp(m1,m2):
m2rows,m2cols = len(m2),len(m2[0])
m1rows,m1cols = len(m1),len(m1[0])
ri = range( m1rows )
rj = range( m2cols )
rk = range( m1cols )
if m1cols != m2rows: raise IndexError, "matrices don't match"
return map( lambda i, m1=m1, m2=m2, rj=rj, rk=rk: (
map ( lambda j, m1i=m1[i], m2=m2, rk=rk: (
reduce ( lambda v, k, j=j, m1i=m1i, m2=m2: (
v + m1i[k]*m2[k][j]),
rk, 0)), rj )), ri )

[Note that all non-global variables have to be passed inside the
lambdas via default arguments. This is irritating, but I think fixing
it would be more trouble and expense than it's worth.]

Of 4 implementations this is the slowest yet I've come up with.
Not recommended, unless you fret a lot about "beauty" and "elegance"
and "the Von Neumann bottleneck" and so forth.
Aaron Watters
Department of Computer and Information Sciences
New Jersey Institute of Technology
University Heights
Newark, NJ 07102
phone (201)596-2666
fax (201)596-5777
home phone (908)545-3367
email: aa...@vienna.njit.edu

Anyone who ever said "What's the Big Idea?" knows that Big Ideas
are usually bad ones. -P.J. O'Rourke, _All the Trouble in The World_

Gregor Schmid

unread,
Jan 23, 1995, 8:39:44 AM1/23/95
to


You mixed it up slightly. Try:

>>> XXX = map( lambda x: map (lambda x: [x]*4, [0]*4), [0]*4)


>>> XXX[1][2][3] = 123
>>> XXX
[[[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]], [[0, 0, 0,

0], [0, 0, 0 , 0], [0, 0, 0, 123], [0, 0, 0, 0]], [[0, 0, 0, 0], [0,
0, 0, 0], [0, 0, 0, 0], [0 , 0, 0, 0]], [[0, 0, 0, 0], [0, 0, 0, 0],
[0, 0, 0, 0], [0, 0, 0, 0]]]

Regards,
Greg

Tim Gilbert

unread,
Jan 26, 1995, 11:46:18 AM1/26/95
to
Gregor Schmid (g...@ivu-berlin.de) wrote:
: You mixed it up slightly. Try:

: >>> XXX = map( lambda x: map (lambda x: [x]*4, [0]*4), [0]*4)
: >>> XXX[1][2][3] = 123
: >>> XXX
: [[[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]], [[0, 0, 0,
: 0], [0, 0, 0 , 0], [0, 0, 0, 123], [0, 0, 0, 0]], [[0, 0, 0, 0], [0,
: 0, 0, 0], [0, 0, 0, 0], [0 , 0, 0, 0]], [[0, 0, 0, 0], [0, 0, 0, 0],
: [0, 0, 0, 0], [0, 0, 0, 0]]]

Say, would someone mind explaining to me what exactly that says? I know
what map(), [x]*4, etc do, but what is


lambda x: [x]*4, [0]*4

^^^^^ <-- this part doing?
And how does it all fit together?

--
Tim Gilbert <> gil...@marin.cc.ca.us <> College of Marin, S.F. Bay Area
--
Tim Gilbert <> gil...@marin.cc.ca.us <> College of Marin, S.F. Bay Area

0 new messages