After using Matlab for some time I grew quite fond of its sprintf
function, which is vectorized (vectorization is the crucial part of the question).
Assuming one has a listli=[1,2,3,4,5,6]
,
sprintf("%d %d %d\n", li)
would apply the format on the elements in li
one after another returning
"1 2 3\n4 5 6\n"
as string.
My current solution does not strike as very pythonic:
def my_sprintf(formatstr, args):
#number of arguments for format string:
n=formatstr.count('%')
res=""
#if there are k*n+m elements in the list, leave the last m out
for i in range(n,len(args)+1,n):
res+=formatstr%tuple(args[i-n:i])
return res
What would be the usual/better way of doing it in python?
Would it be possible, without explicitly eliciting the number of expected parameters from the format string (n=formatstr.count('%')
feels like a hack)?
PS: For the sake of simplicity one could assume, that the number of elements in the list is a multiple of number of arguments in the format string.
You could use a variation of the grouper recipe if you get the user to pass in the chunk size.
def sprintf(iterable,fmt, n):
args = zip(*[iter(iterable)] * n)
return "".join([fmt % t for t in args])
Output:
In [144]: sprintf(li,"%.2f %.2f %d\n", 3)
Out[144]: '1.00 2.00 3\n4.00 5.00 6\n'
In [145]: sprintf(li,"%d %d %d\n", 3)
Out[145]: '1 2 3\n4 5 6\n'
You could handle when the chunk size was not a multiple of the list size using izip_longest and str.format but it would not let you specify the types without erroring :
from itertools import izip_longest
def sprintf(iterable, fmt, n, fillvalue=""):
args = izip_longest(*[iter(iterable)] * n, fillvalue=fillvalue)
return "".join([fmt.format(*t) for t in args])
If you split the placeholders or get the user to pass an iterable of placeholders you could catch all the potential issues.
def sprintf(iterable, fmt, sep=" "):
obj = object()
args = izip_longest(*[iter(iterable)] * len(fmt), fillvalue=obj)
return "".join(["{sep}".join([f % i for f, i in zip(fmt, t) if i is not obj]).format(sep=sep) + "\n"
for t in args])
Demo:
In [165]: sprintf(li, ["%.2f", "%d", "%.2f", "%2.f"])
Out[165]: '1.00 2 3.00 4\n5.00 6\n'
In [166]: sprintf(li, ["%d", "%d", "%d"])
Out[166]: '1 2 3\n4 5 6\n'
In [167]: sprintf(li, ["%f", "%f", "%.4f"])
Out[167]: '1.000000 2.000000 3.0000\n4.000000 5.000000 6.0000\n'
In [168]: sprintf(li, ["%.2f", "%d", "%.2f", "%2.f"])
Out[168]: '1.00 2 3.00 4\n5.00 6\n'
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With