On 2016-05-18 16:47, Steven D'Aprano wrote:
Extracting the first N or last N characters of a string is easy with
slicing:

s[:N]  # first N
s[-N:]  # last N

Getting the middle N seems like it ought to be easy:

s[N//2:-N//2]

but that is wrong. It's not even the right length!

py> s = 'aardvark'
py> s[5//2:-5//2]
'rdv'


So after spending a ridiculous amount of time on what seemed like it ought
to be a trivial function, and an embarrassingly large number of off-by-one
and off-by-I-don't-even errors, I eventually came up with this:

def mid(string, n):
    """Return middle n chars of string."""
    L = len(string)
    if n <= 0:
        return ''
    elif n < L:
        Lr = L % 2
        a, ar = divmod(L-n, 2)
        b, br = divmod(L+n, 2)
        a += Lr*ar
        b += Lr*br
        string = string[a:b]
    return string


which works for me:


# string with odd number of characters
py> for i in range(1, 8):
...     print mid('abcdefg', i)
...
d
de
cde
cdef
bcdef
bcdefg
abcdefg
# string with even number of characters
py> for i in range(1, 7):
...     print mid('abcdef', i)
...
c
cd
bcd
bcde
abcde
abcdef



Is this the simplest way to get the middle N characters?

I think your results are inconsistent.

For an odd number of characters you have "abc" + "de" + "fg", i.e. more on the left, but for an even number of characters you have "a" + "bcd" + "ef", i.e. more on the right.


My own solution is:


def mid(string, n):
    """Return middle n chars of string."""
    if n <= 0:
        return ''

    if n > len(string):
        return string

    ofs = (len(string) - n) // 2

    return string[ofs : ofs + n]


If there's an odd number of characters remaining, it always has more on the right.

--
https://mail.python.org/mailman/listinfo/python-list

Reply via email to