Extract the middle N chars of a string

MRAB python at mrabarnett.plus.com
Wed May 18 13:00:10 EDT 2016


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.




More information about the Python-list mailing list