Matlab的类sprintf函数在python中的矢量化

2024-03-28 14:10:10 发布

您现在位置:Python中文网/ 问答频道 /正文

在使用Matlab一段时间后,我对它的sprintf函数非常感兴趣,它是矢量化的(矢量化是问题的关键部分)。在

假设有一个列表li=[1,2,3,4,5,6]

sprintf("%d %d %d\n", li)

将对li中的元素逐个应用格式返回

^{pr2}$

作为字符串。在

我目前的解决方案并不那么像Python:

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

在python中通常/更好的方法是什么?在

如果不从格式字符串中显式地获取预期参数的数目(n=formatstr.count('%')感觉像是一个黑客)是否可能?在

PS:为了简单起见,可以假设列表中元素的数量是格式字符串中参数数量的倍数。在


Tags: the字符串in元素列表for参数格式
2条回答

您可能需要删除for循环中的+=。下面的版本大约比你的快三倍。它甚至在您想在输出中打印%符号的情况下也能工作。因此,格式字符串包含'%%'。在

def my_sprintf(format_str, li):

    n = format_str.count('%') - 2*format_str.count('%%')
    repeats = len(li)//n

    return (format_str*repeats) % tuple(li[:repeats*n])

如果使用更新的.format方法而不是%,则可以采用一种不那么老套的方法。在这种情况下,可以使用string.Formatter().parse()方法来获取format_str中使用的字段列表。在

然后函数如下所示:

^{pr2}$

如果让用户传入块大小,则可以使用grouper recipe的变体。在

def sprintf(iterable,fmt, n):
    args = zip(*[iter(iterable)] * n)
    return "".join([fmt % t for t in args])

输出:

^{pr2}$

当块大小不是列表大小的倍数时,可以使用izip_longest和str.格式但它不允许您在没有错误的情况下指定类型:

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])

如果您拆分占位符或让用户传递一个iterable占位符,您可以捕获所有潜在的问题。在

 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])

演示:

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'

相关问题 更多 >