Extract the middle N chars of a string

Ian Kelly ian.g.kelly at gmail.com
Wed May 18 12:34:12 EDT 2016


On Wed, May 18, 2016 at 9:47 AM, Steven D'Aprano <steve at pearwood.info> 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?

There's an ambiguity in the problem description when N and the length
of the string have different parity, but how about:

def mid(string, n):
    L = len(string)
    a = (L - n) // 2
    return string[a:a+n]

py> for i in range(1, 8):
...     print(mid('abcdefg', i))
...
d
cd
cde
bcde
bcdef
abcdef
abcdefg



More information about the Python-list mailing list