正如标题所示,我试图交换字符串中的其他字符(例如:"abcd"->"badc"(
def coder(s):
ns = list(s)
ns[1::2],ns[::2] = ns[::2],ns[1::2]
return ''.join(ns)
我在上面看到的第一次尝试对具有偶数字符的字符串效果良好,但给出了错误ValueError:尝试将大小为x的序列分配给大小为x+1的具有奇数的扩展切片
def coder(s):
ns = list(s)
if len(s)%2==0:
ns[1::2],ns[::2] = ns[::2],ns[1::2]
else:
lastcar = ns[-1]
ns = ns[:-1]
ns = coder(ns) + lastcar
return ''.join(ns)
我的下一次尝试效果很好,但比我想象的要复杂得多
如何使其更简单?
在Python中可能有大约一百万种不同的方法来实现这一点。一种方法是迭代,如下所示:
def coder(s):
ns = list(s)
for i in range(0, (len(ns) - len(ns)%2) - 1, 2):
ns[i], ns[i+1] = ns[i+1], ns[i]
return ''.join(ns)
如果你想坚持扩展切片,只需在最后一个偶数位停止切片:
def coder(s):
ns = list(s)
end = len(ns)-len(ns)%2
ns[1::2], ns[:end:2] = ns[:end:2], ns[1::2]
return ''.join(ns)
我可能会结合一些你应该熟悉的已知的好片段(如果你不熟悉,就熟悉它们吧!(
从itertools食谱列表中,将字符串分成两组,反转每组,然后将它们重新链接在一起。
import itertools
# from itertools recipes
def grouper(iterable, n, *, incomplete='fill', fillvalue=None):
"Collect data into non-overlapping fixed-length chunks or blocks"
# grouper('ABCDEFG', 3, fillvalue='x') --> ABC DEF Gxx
# grouper('ABCDEFG', 3, incomplete='strict') --> ABC DEF ValueError
# grouper('ABCDEFG', 3, incomplete='ignore') --> ABC DEF
args = [iter(iterable)] * n
if incomplete == 'fill':
return itertools.zip_longest(*args, fillvalue=fillvalue)
if incomplete == 'strict':
return zip(*args, strict=True)
if incomplete == 'ignore':
return zip(*args)
else:
raise ValueError('Expected fill, strict, or ignore')
s = "abcde"
def swap_chars(s):
"""
Swap every other letter of a string, returning the resulting mix.
>>> swap_chars('abcd')
'bacd'
>>> swap_chars('abcde')
'bacde'
"""
chunks = grouper(s, 2, fillvalue='')
return ''.join(itertools.chain.from_iterable(reversed(chunk) for chunk in chunks))
或者,您可以获取一个列表中的所有偶数索引字符,另一个中的所有奇数索引字符,并以相反的顺序将它们与zip_longest
和chain.from_iterable
重新组合。
import itertools
s = 'abcdefghijk'
def swap_chars(s):
mixed = itertools.zip_longest(s[1::2], s[0::2], fillvalue='')
return ''.join(itertools.chain.from_iterable(mixed))
这甚至可以很好地推广到大于2 的组
def swap_n_chars(s, n=2):
groups = [s[i::n] for i in range(n)]
mixed = itertools.zip_longest(*reversed(groups), fillvalue='')
return ''.join(itertools.chain.from_iterable(mixed))
然而,您可能会注意到,您刚刚重新发明了grouper
:(