切换字符串中的每对字符

Jac*_*ack 5 python string performance python-2.7

例如,拥有字符串:

abcdefghijklmnopqrstuvwxyz
Run Code Online (Sandbox Code Playgroud)

应该导致这样的事情:

badcfehgjilknmporqtsvuxwzy
Run Code Online (Sandbox Code Playgroud)

我怎么去呢?

我想到了一些效率不高的东西,例如:

s = str(range(ord('a'), ord('z') + 1))
new_s = ''
for i in xrange(len(s)):
    if i != 0 and i % 2 == 0:
        new_s += '_' + s[i]
    else:
        new_s += s[i]
# Now it should result in a string such as 'ab_cd_ef_...wx_yz'
l = new_s.split('_')
for i in xrange(len(l)):
    l[i] = l[i][::-1]
result = str(l)
Run Code Online (Sandbox Code Playgroud)

有没有更好的方法?某种方式更有效或更一般,所以我也可以更轻松地用3个字母去做?

Zda*_*daR 7

你可以使用zip()woud返回元组列表的函数[(b,a), (d,c), ...].join()对元组和列表元素的应用方法.

a = "abcdefghijklmnopqrstuvwxyz"
# a[::2] = "acegikmoqsuwy"
# a[1::2] = "bdfhjlnprtvx"
print "".join("".join(i) for i in zip(a[1::2], a[::2]))
>>> badcfehgjilknmporqtsvuxwzy
Run Code Online (Sandbox Code Playgroud)

编辑:要处理奇数长度字符串的情况,如@Ashwini和@ TigerhawkT3所示,您可以将代码更改为:

print "".join("".join(i) for i in zip(a2, a1)) + a[-1] if len(a)%2 else '' 
Run Code Online (Sandbox Code Playgroud)

  • 奇长字符串怎么样? (2认同)

Ash*_*ary 3

一种不使用任何导入的解决方案是将字符串转换为迭代器,并在迭代期间通过调用迭代器上的 next 来获取下一个字符:

>>> s = "abcdefghijklmnopqrstuvwxyz"
>>> it = iter(s)
>>> ''.join(next(it, '') + c for c in it )
'badcfehgjilknmporqtsvuxwzy'
Run Code Online (Sandbox Code Playgroud)

时间:

>>> s = "abcdefghijklmnopqrstuvwxyz" * 10**5
>>> def func_next_no_cache(s):
    it = iter(s)
    return ''.join([next(it, '') + c for c in it])
...
>>> %timeit func_next_no_cache(s)
1 loops, best of 3: 291 ms per loop
Run Code Online (Sandbox Code Playgroud)

但实际上,呼叫速度next减慢了,因为要寻找nextPython 必须从本地范围开始进入内置函数,让我们缓存它并重试:

>>> def func_next_cache(s, next=next):
    it = iter(s)
    return ''.join([next(it, '') + c for c in it])
...
>>> %timeit func_next_cache(s)
1 loops, best of 3: 241 ms per loop
Run Code Online (Sandbox Code Playgroud)

但最快的解决方案是使用itertools.izip_longest

>>> from itertools import izip_longest
>>> def func_izip_l(s):
    it = iter(s)
    return "".join([b+a for a, b in  izip_longest(it, it, fillvalue='')])
...
>>> %timeit func_izip_l(s)

1 loops, best of 3: 209 ms per loop
Run Code Online (Sandbox Code Playgroud)

当与列表而不是生成器表达式一起使用时,@Joran 的代码也非常接近此代码,但它在内存中创建了两个额外的字符串:

>>> %timeit "".join([b+a for a, b in izip_longest(s[::2], s[1::2], fillvalue="")])
1 loops, best of 3: 212 ms per loop
Run Code Online (Sandbox Code Playgroud)

请注意,如果速度是一个问题,我们应该始终提供一个list/sf/answers/634271711/str.join