Reputation: 12214
I have some data stored in a structured numpy array that I would like to write to a file. Because I'm generating some code to match an existing output format that exported a more visually pleasant table I need to output this data with a varying whitespace delimiter.
Using a basic example:
import numpy as np
x = np.zeros((2,),dtype=('i4,f4,a10'))
x[:] = [(1,2.,'Hello'),(2,3.,'World')]
With a desired output of:
1 2.00 Hello
2 3.00 World
Now, I know I could do this:
for row in x:
print('%i %.2f %s' % (row[0], row[1], row[2]))
Which works fine but it seems overly verbose if you have a lot of columns. Right now there are 8 in my output.
I'm new to Python (coming from MATLAB), is there a more generic statement that I could use to 'roll up' all of the columns? I was thinking something along the lines of print('%i %.2f %s' % val for val in row)
but this just prints 2 generators. When I ran into a generator while using re.split
I could use list()
to get my desired output, but I don't think using something similar with, say, str()
for this case would do what I'm looking for.
Upvotes: 3
Views: 113
Reputation: 231385
If you wrap row
in a tuple
, you don't have to list all the elements. %
formats take a tuple
. row
may display as a tuple
but it is actually a numpy.void
.
for row in x:
print('%i %.2f %s'%tuple(row))
Printing or writing rows in a loop like this is perfectly normal Python.
Class __str__
methods are often written like:
astr=['a header line']
for row in x:
astr.append('%i %.2f %s'%tuple(row))
astr='\n'.join(astr)
producing a string of joined lines.
A comprehension equivalent could be:
'\n'.join('%i %.2f %s'%tuple(row) for row in x)
Since you are using Python3, you could also use the .format
approach, but I suspect the %
style is closer to what you are using in MATLAB.
Upvotes: 1
Reputation: 485
First:
Regarding your implicit question with the generators;
you can "stringify" a generator for example with str.join
:
>>> gen = (i.upper() for i in "teststring")
>>> print(''.join(gen))
TESTSTRING
Second: To the actual question: It is a little bit more generic, than your approach, but it is still not really satisfying.
formats = [
("{}", 1), # format and number of spaces for row[0]
("{.2f}", 4), # the same for row[1]
("{}", 0) # and row[2]
]
for row in x:
lst = [f.format(d) + (" "*s) for (f, s, d) in zip(formats, row)]
print(*lst, sep='')
It just provides a better overview over each format.
Upvotes: 1