Path: csiph.com!fu-berlin.de!uni-berlin.de!not-for-mail From: MRAB Newsgroups: comp.lang.python Subject: Re: Extract the middle N chars of a string Date: Wed, 18 May 2016 18:00:10 +0100 Lines: 92 Message-ID: References: <573c8e97$0$1596$c3e8da3$5496439d@news.astraweb.com> <7c327e41-62ef-4b1f-5914-5e939b377bef@mrabarnett.plus.com> Mime-Version: 1.0 Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 7bit X-Trace: news.uni-berlin.de DzAeG+uD2zSuj188VRiJegYpzrVso1c8xCRtvlGz4d7g== Return-Path: X-Original-To: python-list@python.org Delivered-To: python-list@mail.python.org X-Spam-Status: OK 0.001 X-Spam-Evidence: '*H*': 1.00; '*S*': 0.00; 'elif': 0.04; 'seemed': 0.07; '"""return': 0.09; '"a"': 0.09; 'subject:string': 0.09; 'def': 0.13; 'from:addr:mrabarnett.plus.com': 0.16; 'from:addr:python': 0.16; 'from:name:mrab': 0.16; 'left,': 0.16; 'message-id:@mrabarnett.plus.com': 0.16; 'received:192.168.1.4': 0.16; 'received:84.93': 0.16; 'received:84.93.230': 0.16; 'received:io': 0.16; 'received:psf.io': 0.16; 'slicing:': 0.16; 'wrote:': 0.16; 'string': 0.17; 'odd': 0.18; 'function,': 0.22; 'seems': 0.23; 'this:': 0.23; 'header:In-Reply-To:1': 0.24; 'header:User-Agent:1': 0.26; 'right.': 0.27; 'print': 0.30; 'received:84': 0.32; 'getting': 0.33; "d'aprano": 0.33; 'errors,': 0.33; 'steven': 0.33; 'i.e.': 0.35; 'but': 0.36; 'to:addr:python- list': 0.36; 'subject:: ': 0.37; 'subject:the': 0.39; 'received:192': 0.39; 'to:addr:python.org': 0.40; 'easy': 0.60; 'your': 0.60; 'more': 0.63; 'results': 0.66 X-CM-Score: 0.00 X-CNFS-Analysis: v=2.1 cv=bsGxfxui c=1 sm=1 tr=0 a=0nF1XD0wxitMEM03M9B4ZQ==:117 a=0nF1XD0wxitMEM03M9B4ZQ==:17 a=L9H7d07YOLsA:10 a=9cW_t1CCXrUA:10 a=s5jvgZ67dGcA:10 a=IkcTkHD0fZMA:10 a=8jN15IdHnAHJlfbTzlQA:9 a=3d0ZAhBXodZrHBto:21 a=r9ucADy88jF2cJJI:21 a=QEXdDO2ut3YA:10 X-AUTH: mrabarnett@:2500 User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:45.0) Gecko/20100101 Thunderbird/45.1.0 In-Reply-To: <573c8e97$0$1596$c3e8da3$5496439d@news.astraweb.com> X-BeenThere: python-list@python.org X-Mailman-Version: 2.1.22 Precedence: list List-Id: General discussion list for the Python programming language List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Mailman-Original-Message-ID: <7c327e41-62ef-4b1f-5914-5e939b377bef@mrabarnett.plus.com> X-Mailman-Original-References: <573c8e97$0$1596$c3e8da3$5496439d@news.astraweb.com> Xref: csiph.com comp.lang.python:108778 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.