用Python交换字符串中相邻字符对的最简单方法是什么?

30
我想要交换字符串中每一对字符的位置。例如将'2143'变为'1234',将'badcfe'变为'abcdef'
在Python中要如何实现?
20个回答

30

一行代码:

>>> s = 'badcfe'
>>> ''.join([ s[x:x+2][::-1] for x in range(0, len(s), 2) ])
'abcdef'
  • s[x:x+2] 返回从 x 到 x+2 的字符串切片;它也适用于奇数长度的 s。
  • [::-1] 可以在 Python 中翻转字符串
  • range(0, len(s), 2) 返回 0, 2, 4, 6 ... 直到 x < len(s)

24
在Python中交换两个元素的常规方法是:
a, b = b, a

在我看来,您只需要使用扩展切片来完成相同的操作。但是,由于字符串是不可变的,所以这会稍微复杂一些;因此,您需要将其转换为列表,然后再转回字符串。
因此,我会按照以下方式处理:

>>> s = 'badcfe'
>>> t = list(s)
>>> t[::2], t[1::2] = t[1::2], t[::2]
>>> ''.join(t)
'abcdef'

保罗或法比安,除了抛出异常之外,你们希望对无效输入发生什么? - Duncan

9
这里有一种方法...
>>> s = '2134'
>>> def swap(c, i, j):
...  c = list(c)
...  c[i], c[j] = c[j], c[i]
...  return ''.join(c)
...
>>> swap(s, 0, 1)
'1234'
>>>

你的参数中有一个's',而你的主体中没有's'!已在编辑中修复。 - Spacedman
2
s = '2143' not '2134',您使用了未定义的变量c。 - cocobear
1
那只交换了第一个字符,如果你想要交换所有字符,你必须将字符串拆分并连接 len(s)/2 次。 - Lennart Regebro

4
''.join(s[i+1]+s[i] for i in range(0, len(s), 2)) # 10.6 usec per loop

或者

''.join(x+y for x, y in zip(s[1::2], s[::2])) # 10.3 usec per loop

或者,如果字符串长度为奇数:
''.join(x+y for x, y in itertools.izip_longest(s[1::2], s[::2], fillvalue=''))

请注意,这不适用于旧版本的Python(如果我没有记错,旧版本低于2.5)。
该基准测试是在python-2.7-8.fc14.1.x86_64和Core 2 Duo 6400 CPU上运行的,使用s='0123456789'*4

1
对于奇数长度的字符串 s,第一个产生 IndexError: string index out of range 错误,第二个将删除最后一个字符。 - Paulo Scardine
1
@paulo: 那么奇数长度的字符串对于 OP 的要求是什么? - SilentGhost
@Paulo Scardine:你说得对,但问题不够具体。 - Cristian Ciupitu
@SilentGhost:由于没有偶数长度的要求,因此暗示了任意长度。 - Paulo Scardine
1
@paulo:OP在谈论一个“对”字符,而示例并没有涵盖奇数长度的字符串,因此可以暗示只考虑偶数长度的字符串。 - SilentGhost
@SilentGhost:对于偶数长度的字符串,代码本身就不好看。 :-) - Paulo Scardine

4

如果性能或优雅并不是问题,你只需要清晰明了的完成任务,那么可以使用以下代码:

def swap(text, ch1, ch2):
    text = text.replace(ch2, '!',)
    text = text.replace(ch1, ch2)
    text = text.replace('!', ch1)
    return text

这允许你交换或替换字符或子字符串。例如,要在文本中交换 'ab' <-> 'de':

_str = "abcdefabcdefabcdef"
print swap(_str, 'ab','de') #decabfdecabfdecabf

4
这不会在应用方面非常有限吗? - Kaustubh Karkare

2

不需要列出清单。以下适用于长度为偶数的字符串:

r = ''
for in in range(0, len(s), 2) :
  r += s[i + 1] + s[i]
s = r

2
如果字符串长度是奇数,怎么办? - Abdelrahman Elkady

2

按两个字符为一组循环遍历字符串并交换:

def oddswap(st):
    s = list(st)
    for c in range(0,len(s),2):
        t=s[c]
        s[c]=s[c+1]
        s[c+1]=t

    return "".join(s)

提供:

>>> s
'foobar'
>>> oddswap(s)
'ofbora'

对于奇数长度的字符串,会出现IndexError异常。


1

要交换字符串a中位置l和r的字符

def swap(a, l, r):
    a = a[0:l] + a[r] + a[l+1:r] + a[l] + a[r+1:]
    return a

例子: swap("aaabcccdeee", 3, 7) 返回 "aaadcccbeee"


1
一个更普遍的答案是,你可以使用这种方法对元组或字符串进行任何单个成对交换。
# item can be a string or tuple and swap can be a list or tuple of two
# indices to swap
def swap_items_by_copy(item, swap):
   s0 = min(swap)
   s1 = max(swap)
   if isinstance(item,str):
        return item[:s0]+item[s1]+item[s0+1:s1]+item[s0]+item[s1+1:]
   elif isinstance(item,tuple):
        return item[:s0]+(item[s1],)+item[s0+1:s1]+(item[s0],)+item[s1+1:]
   else:
        raise ValueError("Type not supported")

然后您可以像这样调用它:
>>> swap_items_by_copy((1,2,3,4,5,6),(1,2))
(1, 3, 2, 4, 5, 6)
>>> swap_items_by_copy("hello",(1,2))
'hlelo'
>>> 

感谢Python在索引不存在的情况下提供了空字符串或元组。

0
def revstr(a):
    b=''
    if len(a)%2==0:
        for i in range(0,len(a),2):
            b += a[i + 1] + a[i]
        a=b
    else:
        c=a[-1]
        for i in range(0,len(a)-1,2):
            b += a[i + 1] + a[i]
        b=b+a[-1]
        a=b
    return b
a=raw_input('enter a string')
n=revstr(a)
print n

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接