Parsing info into a 2d list

M

Matthew Walsh

Whats wrong with the following code?
using pythonWin I get the following error:

Traceback (most recent call last):
File "C:\Python23\Lib\site-packages\pythonwin\pywin\framework\scriptutils.py",
line 310, in RunScript
exec codeObject in __main__.__dict__
File "C:\Documents and Settings\Administrator\My
Documents\file_parser.py", line 16, in ?
rownum = range(eval(nrows))
TypeError: object doesn't support item assignment
f = open('f:\input.dat')
feed= f.read()
lines = feed.split('\n')
ncols = lines[0].split()[1]
nrows = lines[1].split()[1]
xllcorner = lines[2].split()[1]
yllcorner = lines[3].split()[1]
cellsize = lines[4].split()[1]
NoData = lines[5].split()[1]

colnum = range(eval(ncols))
rownum = range(eval(nrows))

for r in rownum:
for c in colnum:
slope[r][c]= eval(lines[6+r].split()[c])

f.close()
 
A

Alex Martelli

Matthew Walsh said:
Whats wrong with the following code?
using pythonWin I get the following error:

Traceback (most recent call last):
File
"C:\Python23\Lib\site-packages\pythonwin\pywin\framework\scriptutils.py",
line 310, in RunScript
exec codeObject in __main__.__dict__
File "C:\Documents and Settings\Administrator\My
Documents\file_parser.py", line 16, in ?
rownum = range(eval(nrows))
TypeError: object doesn't support item assignment
f = open('f:\input.dat')
feed= f.read()
lines = feed.split('\n')
ncols = lines[0].split()[1]
nrows = lines[1].split()[1]
xllcorner = lines[2].split()[1]
yllcorner = lines[3].split()[1]
cellsize = lines[4].split()[1]
NoData = lines[5].split()[1]

colnum = range(eval(ncols))
rownum = range(eval(nrows))

for r in rownum:
for c in colnum:
slope[r][c]= eval(lines[6+r].split()[c])

f.close()

Looks like the message is off by a few lines. The item assignment
you're trying to do is in the body of the nested for, and since 'slope'
isn't ever assigned anything anywhere it's hard to guess what it is, but
apparently its items don't support item assignment.


Alex
 
B

Bengt Richter

Whats wrong with the following code?
Why not print out the data it's using as it goes? That's only 5 lines.
There might be a clue.
using pythonWin I get the following error:

Traceback (most recent call last):
File "C:\Python23\Lib\site-packages\pythonwin\pywin\framework\scriptutils.py",
line 310, in RunScript
exec codeObject in __main__.__dict__
File "C:\Documents and Settings\Administrator\My
Documents\file_parser.py", line 16, in ?
rownum = range(eval(nrows))
TypeError: object doesn't support item assignment
f = open('f:\input.dat')
feed= f.read()
lines = feed.split('\n')
ncols = lines[0].split()[1]
nrows = lines[1].split()[1]
xllcorner = lines[2].split()[1]
yllcorner = lines[3].split()[1]
cellsize = lines[4].split()[1]
NoData = lines[5].split()[1]
Stylistically, that's a lot of re-typing. E.g., see below for alternative
Also, why not put all those on one line? Or don't you have control over input format?
colnum = range(eval(ncols))
rownum = range(eval(nrows))
the best way to convert from string to integer is int(thestring), not eval(thestring).
The latter risks bad surprises if thestring has not been verified safe.
for r in rownum:
for c in colnum:
slope[r][c]= eval(lines[6+r].split()[c])
What is slope? Nested list representation of 2D array?
what is the format of the items on the line? Presumably numeric literals, but ints? floats?

I'll assume floats would be safe, but I special cased-NoData.

Have you considered making slope a list subclass instance that you can access your
named values from as well as slope[r][c] for data values, and initialize like
f = file('f:\input.dat'); slope = Slope(f) ? E.g., (not tested beyond what you see ;-)

----< slope.py >------------------------
class Slope(list):
"""
2D data container initialized from text line sequence or iterator yielding:
... ncols ...
... nrows ...
... xllcorner ...
... yllcorner ...
... cellsize ...
... NoData ...
<row 0>
<row 1>
<row nrows-1>
where a row is
col0value col1value col2value ... col<ncols-1>value
If the iterator is an open file, the caller is responsible for closing it.
"""
def __init__(self, lines):
lines = iter(lines)
for name in 'ncols nrows xllcorner yllcorner cellsize'.split():
setattr(self, name, int(lines.next().split()[1]))
self.NoData = lines.next().split()[1]
mx = []
for r in xrange(self.nrows):
mx.append([float(v) for v in lines.next().split()])
list.__init__(self, mx)
def __str__(self):
return '\n'.join(['<Slopes object:']+map(str, list(self))+['>'])

def test():
mx = Slope("""\
?? 3
?? 2
?? 111
?? 222
?? 333
?? NoDataToken??
0 1 2
3 4 5
""".splitlines())
for name in 'ncols nrows xllcorner yllcorner cellsize NoData'.split():
print '%10s: %r' % (name, getattr(mx, name))
print mx
for r in xrange(mx.nrows):
for c in xrange(mx.ncols):
print mx[r][c],

if __name__ == '__main__':
test()
----------------------------------------

I put ?? as place holders since I didn't know what you had there.

Result:

[18:39] C:\pywk\clp>slope.py
ncols: 3
nrows: 2
xllcorner: 111
yllcorner: 222
cellsize: 333
NoData: 'NoDataToken??'
<Slopes object:
[0.0, 1.0, 2.0]
[3.0, 4.0, 5.0]0.0 1.0 2.0 3.0 4.0 5.0

Regards,
Bengt Richter
 
B

Bengt Richter

]
----< slope.py >------------------------ [...]
def __init__(self, lines):
lines = iter(lines)
for name in 'ncols nrows xllcorner yllcorner cellsize'.split():
setattr(self, name, int(lines.next().split()[1]))
self.NoData = lines.next().split()[1]
mx = []
for r in xrange(self.nrows):
mx.append([float(v) for v in lines.next().split()])
list.__init__(self, mx)
def __str__(self):
return '\n'.join(['<Slopes object:']+map(str, list(self))+['>'])
I don't like that useless separate mx. Below seems better, since apparently the base class
supplies an initialized empty list (though I'm not sure exactly how that is implemented):

def __init__(self, lines):
lines = iter(lines)
for name in 'ncols nrows xllcorner yllcorner cellsize'.split():
setattr(self, name, int(lines.next().split()[1]))
self.NoData = lines.next().split()[1]
for r in xrange(self.nrows):
self.append([float(v) for v in lines.next().split()])

Always room for improvement ;-)

Regards,
Bengt Richter
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,209
Messages
2,571,088
Members
47,687
Latest member
IngridXxj

Latest Threads

Top