Home > database >  How to implement center() by padding the extra character always on the left?
How to implement center() by padding the extra character always on the left?

Time:09-13

The builtin center() padding the extra character either on left or on the right depending on the string's length, e.g. 'bar'.center(10, '-') is ---bar----, the extra - is on the right but hi.center(9,'-') is ----hi---, the extra is on the left.

But in my case I need the extra padding(if any) always on the left. What is the simple way to do that (as there are many ways to do that) ?

BTW, why does builtin center() implement in this way (actually I am more curious in this)?

CodePudding user response:

You can implement your own version that left-pads the string. It's pretty simple, you make sure center creates an even-sized string, then if there is a reminder left you pad it on the left

In [1]: def left_center(word, sep, length):
   ...:     reminder = (length - len(word)) % 2
   ...:     return f'{reminder*sep}{word.center(length-reminder, sep)}'
   ...:

In [2]: left_center('bar', '-', 10)
Out[2]: '----bar---'

In [3]: left_center('hi', '-', 9)
Out[3]: '----hi---'

for left_center('bar', '-', 10) it does this:

reminder = (10 - 3) % 2 # which is equal to 1
f'{1*"-"}{"bar".center(9, "-")} # '----bar---'

CodePudding user response:

The original implementation of str.center was added here, in 1990:

# Center a string
def center(s, width):
    n = len(s)
    if n >= width: return s
    return ' '*((width-n)/2)    s   ' '*(width -(width-n)/2)

It was changed a year later, in 1991, to

# Center a string
def center(s, width):
    """center(s, width) -> string
    Return a center version of s, in a field of the specified
    width. padded with spaces as needed.  The string is never
    truncated.
    """
    n = width - len(s)
    if n <= 0: return s
    half = n/2
    if n%2 and width%2:
        # This ensures that center(center(s, i), j) = center(s, j)
        half = half 1
    return ' '*half    s   ' '*(n-half)

and the current C implementation found here does

static PyObject *
stringlib_center_impl(PyObject *self, Py_ssize_t width, char fillchar)
/*[clinic end generated code: output=d8da2e055288b4c2 input=3776fd278765d89b]*/
{
    Py_ssize_t marg, left;

    if (STRINGLIB_LEN(self) >= width) {
        return return_self(self);
    }

    marg = width - STRINGLIB_LEN(self);
    left = marg / 2   (marg & width & 1);

    return pad(self, left, marg - left, fillchar);
}

I suspect the "why" for the current implementation is the

This ensures that center(center(s, i), j) = center(s, j)

comment, but you'd have to ask Guido for confirmation.

  • Related