首页 文章

将零填充到字符串的最好方法

提问于
浏览
1074

使用零填充数字字符串的最Pythonic方法是什么,即数字字符串是否具有特定长度?

13 回答

  • 4

    字符串:

    >>> n = '4'
    >>> print n.zfill(3)
    004
    

    对于数字:

    >>> n = 4
    >>> print '%03d' % n
    004
    >>> print format(n, '03') # python >= 2.6
    004
    >>> print '{0:03d}'.format(n)  # python >= 2.6
    004
    >>> print '{foo:03d}'.format(foo=n)  # python >= 2.6
    004
    >>> print('{:03d}'.format(n))  # python >= 2.7 + python3
    004
    >>> print('{0:03d}'.format(n))  # python 3
    004
    >>> print(f'{n:03}') # python >= 3.6
    004
    

    String formatting documentation .

  • -2

    只需使用字符串对象的rjust方法即可 .

    这个例子将生成一个10个字符长的字符串,根据需要填充 .

    >>> t = 'test'
    >>> t.rjust(10, '0')
    >>> '000000test'
    
  • 14

    对于数字:

    print "%05d" % number
    

    另见:Python: String formatting .

    EDIT :值得注意的是,截至2008年12月3日,这种格式化方法已弃用,而采用 format 字符串方法:

    print("{0:05d}".format(number)) # or
    print(format(number, "05d"))
    

    有关详细信息,请参阅PEP 3101 .

  • 16
    >>> '99'.zfill(5)
    '00099'
    >>> '99'.rjust(5,'0')
    '00099'
    

    如果你想要相反:

    >>> '99'.ljust(5,'0')
    '99000'
    
  • 45

    适用于Python 2和Python 3:

    >>> "{:0>2}".format("1")  # Works for both numbers and strings.
    '01'
    >>> "{:02}".format(1)  # Only works for numbers.
    '01'
    
  • 286

    str(n).zfill(width) 将适用于 string s, int s, float s ...并且兼容Python 2.x和3.x:

    >>> n = 3
    >>> str(n).zfill(5)
    '00003'
    >>> n = '3'
    >>> str(n).zfill(5)
    '00003'
    >>> n = '3.0'
    >>> str(n).zfill(5)
    '003.0'
    
  • 1737

    对于那些来这里了解而不仅仅是快速回答的人 . 我特别为时间字符串做这些:

    hour = 4
    minute = 3
    "{:0>2}:{:0>2}".format(hour,minute)
    # prints 04:03
    
    "{:0>3}:{:0>5}".format(hour,minute)
    # prints '004:00003'
    
    "{:0<3}:{:0<5}".format(hour,minute)
    # prints '400:30000'
    
    "{:$<3}:{:#<5}".format(hour,minute)
    # prints '4$$:3####'
    

    “0”符号用“2”填充字符替换,默认为空格“>”符号将字符串左边的所有2“0”字符对齐“:”符号format_spec

  • 88
    width = 10
    x = 5
    print "%0*d" % (width, x)
    > 0000000005
    

    有关所有令人兴奋的细节,请参阅打印文档!

    Update for Python 3.x (7.5 years later)

    最后一行现在应该是:

    print("%0*d" % (width, x))
    

    print() 现在是一个函数,而不是一个声明 . 请注意,我仍然更喜欢Old School printf() 风格,因为,IMNSHO,它读起来更好,因为,嗯,我自1980年1月以来一直在使用那种符号 . 某些东西......老狗......某事......新技巧 .

  • 7

    使用零填充数字字符串的最pythonic方法是什么,即数字字符串是否具有特定长度?

    str.zfill 专门用于执行此操作:

    >>> '1'.zfill(4)
    '0001'
    

    请注意,它专门用于处理请求的数字字符串,并将 +- 移动到字符串的开头:

    >>> '+1'.zfill(4)
    '+001'
    >>> '-1'.zfill(4)
    '-001'
    

    这是 str.zfill 的帮助:

    >>> help(str.zfill)
    Help on method_descriptor:
    
    zfill(...)
        S.zfill(width) -> str
    
        Pad a numeric string S with zeros on the left, to fill a field
        of the specified width. The string S is never truncated.
    

    表现

    这也是替代方法中性能最高的方法:

    >>> min(timeit.repeat(lambda: '1'.zfill(4)))
    0.18824880896136165
    >>> min(timeit.repeat(lambda: '1'.rjust(4, '0')))
    0.2104538488201797
    >>> min(timeit.repeat(lambda: f'{1:04}'))
    0.32585487607866526
    >>> min(timeit.repeat(lambda: '{:04}'.format(1)))
    0.34988890308886766
    

    为了最佳地比较 % 方法的苹果与苹果(注意它实际上较慢),否则将预先计算:

    >>> min(timeit.repeat(lambda: '1'.zfill(0 or 4)))
    0.19728074967861176
    >>> min(timeit.repeat(lambda: '%04d' % (0 or 1)))
    0.2347015216946602
    

    实施

    通过一点挖掘,我在Objects/stringlib/transmogrify.h中找到了 zfill 方法的实现:

    static PyObject *
    stringlib_zfill(PyObject *self, PyObject *args)
    {
        Py_ssize_t fill;
        PyObject *s;
        char *p;
        Py_ssize_t width;
    
        if (!PyArg_ParseTuple(args, "n:zfill", &width))
            return NULL;
    
        if (STRINGLIB_LEN(self) >= width) {
            return return_self(self);
        }
    
        fill = width - STRINGLIB_LEN(self);
    
        s = pad(self, fill, 0, '0');
    
        if (s == NULL)
            return NULL;
    
        p = STRINGLIB_STR(s);
        if (p[fill] == '+' || p[fill] == '-') {
            /* move sign to beginning of string */
            p[0] = p[fill];
            p[fill] = '0';
        }
    
        return s;
    }
    

    让我们来看看这个C代码 .

    它首先在位置上解析参数,这意味着它不允许关键字参数:

    >>> '1'.zfill(width=4)
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    TypeError: zfill() takes no keyword arguments
    

    然后检查它是否长度相同或更长,在这种情况下它返回字符串 .

    >>> '1'.zfill(0)
    '1'
    

    zfill 调用 pad (此 pad 函数也由 ljustrjustcenter 调用) . 这基本上将内容复制到一个新字符串并填充填充 .

    static inline PyObject *
    pad(PyObject *self, Py_ssize_t left, Py_ssize_t right, char fill)
    {
        PyObject *u;
    
        if (left < 0)
            left = 0;
        if (right < 0)
            right = 0;
    
        if (left == 0 && right == 0) {
            return return_self(self);
        }
    
        u = STRINGLIB_NEW(NULL, left + STRINGLIB_LEN(self) + right);
        if (u) {
            if (left)
                memset(STRINGLIB_STR(u), fill, left);
            memcpy(STRINGLIB_STR(u) + left,
                   STRINGLIB_STR(self),
                   STRINGLIB_LEN(self));
            if (right)
                memset(STRINGLIB_STR(u) + left + STRINGLIB_LEN(self),
                       fill, right);
        }
    
        return u;
    }
    

    在调用 pad 之后, zfill 将任何原先前面的 +- 移动到字符串的开头 .

    请注意,对于原始字符串实际上是数字不是必需的:

    >>> '+foo'.zfill(10)
    '+000000foo'
    >>> '-foo'.zfill(10)
    '-000000foo'
    
  • 33
    >>> width = 4
    >>> x = 5
    >>> print("%0*d" %(width,x))
    >>> 00005
    

    这将在python 3.x中工作

  • 42

    对于保存为整数的邮政编码:

    >>> a = 6340
    >>> b = 90210
    >>> print '%05d' % a
    06340
    >>> print '%05d' % b
    90210
    
  • 4

    快速计时比较:

    setup = '''
    from random import randint
    def test_1():
        num = randint(0,1000000)
        return str(num).zfill(7)
    def test_2():
        num = randint(0,1000000)
        return format(num, '07')
    def test_3():
        num = randint(0,1000000)
        return '{0:07d}'.format(num)
    def test_4():
        num = randint(0,1000000)
        return format(num, '07d')
    def test_5():
        num = randint(0,1000000)
        return '{:07d}'.format(num)
    def test_6():
        num = randint(0,1000000)
        return '{x:07d}'.format(x=num)
    def test_7():
        num = randint(0,1000000)
        return str(num).rjust(7, '0')
    '''
    import timeit
    print timeit.Timer("test_1()", setup=setup).repeat(3, 900000)
    print timeit.Timer("test_2()", setup=setup).repeat(3, 900000)
    print timeit.Timer("test_3()", setup=setup).repeat(3, 900000)
    print timeit.Timer("test_4()", setup=setup).repeat(3, 900000)
    print timeit.Timer("test_5()", setup=setup).repeat(3, 900000)
    print timeit.Timer("test_6()", setup=setup).repeat(3, 900000)
    print timeit.Timer("test_7()", setup=setup).repeat(3, 900000)
    
    
    > [2.281613943830961, 2.2719342631547077, 2.261691106209631]
    > [2.311480238815406, 2.318420542148333, 2.3552384305184493]
    > [2.3824197456864304, 2.3457239951596485, 2.3353268829498646]
    > [2.312442972404032, 2.318053102249902, 2.3054072168069872]
    > [2.3482314132374853, 2.3403386400002475, 2.330108825844775]
    > [2.424549090688892, 2.4346475296851438, 2.429691196530058]
    > [2.3259756401716487, 2.333549212826732, 2.32049893822186]
    

    我对不同的重复进行了不同的测试 . 差异并不大,但在所有测试中, zfill 解决方案最快 .

  • 2

    您也可以重复"0",将其添加到 str(n) 并获取最右边的宽度切片 . 快速而肮脏的小表达 .

    def pad_left(n, width, pad="0"):
        return ((pad * width) + str(n))[-width:]
    

相关问题