开发者

zero fill empty spaces at specific locations

开发者 https://www.devze.com 2023-03-12 02:00 出处:网络
I have a small question. I have a file in the following format: 1 2 1 2 3 1 2 1 2 3 4 2 4 The values in the code actually represent numbers(not necessarily single digit), but they can be any numb

I have a small question. I have a file in the following format:

1 2 
1 2 3
1 2
1 2 3 4
2 4

The values in the code actually represent numbers(not necessarily single digit), but they can be any number, can be floating point values too.

Input file: For a particular row, each number is separated from another by a single whitespace (the separator can't be anything other than whitespace).

My task: I want to zero fill the empty spaces in such a way that it looks like this, i.e. fill up the empty spaces in such a way that it gives me a nice matrix-looking format:

1 2 0 0
1 2 3 0
1 2 0 0
1 2 3 4
2 4 0 0

Output file: Same rule applies. For a particular row, each number is separated from another by a single whitespace only.开发者_开发技巧

Language used: Python(or may be Shell, if that's possible)

I know there is this function called zfill, but I don't think that would be much of a help to me.

My solution: Find the (maximum length/2) of each line, using len and max functions. Then, using split(), fill up with zeros at appropriate places of each line. I am afraid it might turn into a dirty code and I'm sure there are better ways to accomplish this task.

Any suggestion is welcome.

Thank you!


Assume myfile is the open file. We use izip_longest from itertools to iterate over the columns of the input file, filling in "0" for missing values:

[('1', '1', '1', '1', '2'),  ('2', '2', '2', '2', '4'),      
 ('0', '3', '0', '3', '0'), ('0', '0', '0', '4', '0')]

Then we simply zip this output again to restore the rows with zeroes filled in. This is the code:

from itertools import izip_longest

rows = [line.split() for line in myfile]            # Read
rows = zip(*izip_longest(*rows, fillvalue="0"))     # Add zeroes
print "\n".join(" ".join(row) for row in rows)      # Write

EDIT: The above (imho elegant) solution is slightly slower (8.55 usec vs. 7.08 usec) than the naive approach:

rows = [line.split() for line in myfile]
maxlen = max(len(x) for x in rows)
for row in rows:
    print " ".join(row + ["0"] * (maxlen - len(row)))

Re: comment

If you want to align the columns it's easiest to amend the first approach, because there we already have the numbers arranged by column at one point. That makes finding the column width easy.

from itertools import izip_longest

rows = [line.split() for line in myfile]
columns = list(izip_longest(*rows, fillvalue="0"))
column_width = [max(len(num) for num in col) for col in columns]

# We make a template of the form "{0:>a} {1:>b} {2:>c} ...",
# where a, b, c, ... are the column widths:
column_template = "{{{0}:>{1}s}}"
row_template = " ".join(column_template.format(i, n) for
    i, n in enumerate(column_width))

print "\n".join(row_template.format(*row) for row in zip(*columns))


You could always read each lines and count the number of numbers that you have. Then you can write this line into a new temporary file and append the fillings after and you can overwrite the original file with this temporary file if required.

To count the number of numbers you can use str.split() with your white-space character as separator then you just get the number of entries in the list. Appending your filling number should be quite straight forward.

More documentation on str.split()


Something like this - but i also believe that it should be updated since not all is clear in your question:

tst="""
       1 2
       1 2 3
       1 2
       1 2 3 4
       2 4
    """
res = [line for line in tst.split('\n') if line != '']
mLen = max(len(line) for line in res)   
print '\n'.join(list((line + ' 0' * ((mLen - len(line))//2) for line in res)))
0

精彩评论

暂无评论...
验证码 换一张
取 消