views:

70

answers:

3

I have some values that I want to write in a text file with the constraint that each value has to go to a particular column of each line.

For example, lets say that I have values = [a, b, c, d] and I want to write them in a line so that a is going to be written in the 10th column of the line, b on the 25th, c on the 34th, and d on the 48th column.

How would I do this in python?

Does python have something like column.insert(10, a)? It would make my life way easier.

I appreciate your hep.

+2  A: 

In this case, I'd think you'd just use the padding functions with python's string formatting syntax.

Something like "%10d%15d%9d%14d"%values will place the right-most digit of a,b,c,d on the columns you listed.

If you want to have the left-most digits placed there, then you could use: "%<15d%<9d%<14d%d"%values, and prepend 10 spaces.

EDIT: For some reason I'm having trouble with the above syntax... so I used the newstyle formatting syntax like so:

" "*9 + "{:<14}{:<9}{:<14}{}".format(*values)

This should print, for values=[20,30,403,50]:

.........                                        <-- from " "*9
         20............                          <-- {:<14}
                       30.......                 <-- {:<9}
                                403...........   <-- {:<14}
                                              50 <-- {}
----=----1----=----2----=----3----=----4----=----5    <-- guide
         20            30       403           50 <-- Actual output, all together
jkerian
Actually, that is the tricky part.. The output of the values in the file, does not depend on the white spaces between the values. It depends on the particular columns of the line where each value should be written on
I guess I don't quite understand this relationship. Are you trying to line up all the values? or is there some relationship between the values that are being written and the number of spaces (aside from a padding requirement)?
jkerian
I guess I was looking for smth like your answer. Thanks a lot jkerian!
A: 

You can use the mmap module to memory-map a file.

http://docs.python.org/library/mmap.html

With mmap you can do something like this:

fh = file('your_file', 'wb')
map = mmap.mmap(fh.fileno(), <length of the file you want to create>)
map[10] = a
map[25] = b

Not sure if that is what you're looking for, but it might work :)

It seems I might have misunderstood the question. The old answer is below

Perhaps you're looking for the csv module?

http://docs.python.org/library/csv.html

import csv
fh = open('eggs.csv', 'wb')
spamWriter = csv.writer(fh, delimiter=' ')
spamWriter.writerow(['Spam'] * 5 + ['Baked Beans'])
spamWriter.writerow(['Spam', 'Lovely Spam', 'Wonderful Spam'])
WoLpH
can you give a non-convoluted example of using the csv module to control the width of a column in the text file? for example make column two 10 characters wide? This is what the OP wants.
aaronasterling
If the OP wants that than I have misunderstood. I thought he meant a fixed amount of columns instead. In that case I have another solution :)
WoLpH
-1. 1)You have to know the length of the file advance. 2) not cross platform compatible. 3) requires opening the file in binary mode.
aaronasterling
@AaronMcSmooth: 1. Wheter that is acceptable or not is not given bye the OP. 2. no platform was given. 3. true, but that doesn't have to be a problem. It's just an alternative solution, seemed more useful than writing up a solution about string formatting which would be basically the same as the other solutions here.
WoLpH
+1  A: 
class ColumnWriter(object):
    def __init__(self, columns):
        columns = (-1, ) + tuple(columns)
        widths = (c2 - c1 for c1, c2 in zip(columns, columns[1:]))
        format_codes = ("{" + str(i) + ":>" + str(width) +"}"
                        for i, width in enumerate(widths))
        self.format_string = ''.join(format_codes)

    def get_row(self, values):
        return self.format_string.format(*values)

cw = ColumnWriter((1, 20, 21))
print cw.get_row((1, 2, 3))
print cw.get_row((1, 'a', 'a'))

if you need the columns to vary from row to row, then you can do one liners.

import itertools

for columns in itertools.combinations(range(10), 3):
    print ColumnWriter(columns).get_row(('.','.','.'))

It slacks on the error checking. It needs to check that columns is sorted and that len(values) == len(columns).

It has problems with the value being longer than the area being allocated to hold it but I'm not sure what to do about this. Currently if that occurs, it overwrites the previous column. example:

print ColumnWriter((1, 2, 3)).get_row((1, 1, 'aa'))

If you had an iterable of rows that you wanted to write to a file, you could do something like this

rows = [(1, 3, 4), ('a', 'b', 4), ['foo', 'ten', 'mongoose']]

format = ColumnWriter((20, 30, 50)).get_row
with open(filename, 'w') as fout:
    fout.write("\n".join(format(row) for row in rows))
aaronasterling