使用Python在字符串中交换char的最简单方法是什么?

时间:2011-01-05 14:57:00

标签: python string

我想在字符串中交换每对字符。 '2143'变为'1234''badcfe'变为'abcdef'

我怎样才能在Python中执行此操作?

20 个答案:

答案 0 :(得分:13)

oneliner:

>>> s = 'badcfe'
>>> ''.join([ s[x:x+2][::-1] for x in range(0, len(s), 2) ])
'abcdef'
  • s [x:x + 2]将字符串切片从x返回到x + 2;对于奇数len是安全的。
  • [:: - 1]在Python中反转字符串
  • range(0,len(s),2)返回0,2,4,6 ...而x< LEN(S)

答案 1 :(得分:9)

在Python中交换项目的常用方法是:

a, b = b, a

所以在我看来,你只是对扩展切片做同样的事情。它有点复杂,因为字符串不可变,所以你必须转换为一个列表,然后回到一个字符串,但我要做的是:

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

答案 2 :(得分:6)

这是一种方式......

>>> 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'
>>>

答案 3 :(得分: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异常的奇数长度字符串上失败。

答案 4 :(得分:2)

''.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和带有s='0123456789'*4的Core 2 Duo 6400 CPU上运行。

答案 5 :(得分:2)

如果性能或优雅不是问题,而您只是想要清晰并完成工作,那么只需使用它:

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

答案 6 :(得分:2)

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

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

答案 7 :(得分:0)

还有一种方法:

>>> s='123456'
>>> ''.join([''.join(el) for el in zip(s[1::2], s[0::2])])
'214365'

答案 8 :(得分:0)

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

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"

答案 9 :(得分:0)

虽然上述解决方案确实有效,但我们有一个非常简单的解决方案应该用“外行”的术语来说。仍在学习python和string的人可以使用其他答案,但是如果没有海报者的完整解释而不是“这是可行的”,他们还无法真正理解其工作方式或代码的每个部分在做什么。下面的代码执行字符串中每个第二个字符的交换,对于初学者来说很容易理解它的工作原理。

它只是简单地遍历字符串(任意长度)两次(从0开始,找到第二个字符),然后通过添加当前索引+ 1(第二个字符),然后再加上实际值来创建新的字符串(交换对)索引(第一个字符),例如,将索引1放在索引0处,然后将索引0放在索引1处,这会在字符串的迭代过程中重复进行。

还添加了代码以确保字符串的长度均匀,因为它仅适用于偶数长度。

上面的DrSanjay Bhakkad帖子也是一个很好的文章,适用于偶数或奇数字符串,并且基本上具有与下面相同的功能。

string = "abcdefghijklmnopqrstuvwxyz123"

# use this prior to below iteration if string needs to be even but is possibly odd
if len(string) % 2 != 0:
    string = string[:-1]

# iteration to swap every second character in string
swapped_pair = ""
for i in range(0, len(string), 2):
    swapped_pair += (string[i + 1] + string[i])

# use this after above iteration for any even or odd length of strings
if len(swapped_pair) % 2 != 0:
    swapped_adj += swapped_pair[-1]

print(swapped_pair)

badcfehgjilknmporqtsvuxwzy21 # output if the "needs to be even" code used
badcfehgjilknmporqtsvuxwzy213 # output if the "even or odd" code used

答案 10 :(得分:0)

参加聚会有点晚,但是实际上有一个非常简单的方法可以做到这一点:

您要查找的索引序列可以表示为两个序列的总和:

 0  1  2  3 ...
+1 -1 +1 -1 ...

两者都很容易表达。第一个就是range(N)。对于该范围内的每个i切换的序列是i % 2。您可以通过缩放和偏移来调整切换开关:

         i % 2      ->  0  1  0  1 ...
     1 - i % 2      ->  1  0  1  0 ...
2 * (1 - i % 2)     ->  2  0  2  0 ...
2 * (1 - i % 2) - 1 -> +1 -1 +1 -1 ...

整个表达式简化为i + 1 - 2 * (i % 2),您可以使用它几乎直接将字符串连接起来:

result = ''.join(string[i + 1 - 2 * (i % 2)] for i in range(len(string)))

这仅适用于偶数长度的字符串,因此您可以使用min检查溢出:

N = len(string)
result = ''.join(string[min(i + 1 - 2 * (i % 2), N - 1)] for i in range(N))

基本上是单行代码,不需要任何超出索引范围的迭代器,也不需要一些非常简单的整数数学。

答案 11 :(得分:0)

一个更一般的答案...您可以使用此方法对元组或字符串进行任何成对交换:

# 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在索引引用不存在的切片的情况下给出了空字符串或元组。

答案 12 :(得分:0)

{{1}}

答案 13 :(得分:0)

>>> import ctypes
>>> s = 'abcdef'
>>> mutable = ctypes.create_string_buffer(s)
>>> for i in range(0,len(s),2):
>>>     mutable[i], mutable[i+1] = mutable[i+1], mutable[i]
>>> s = mutable.value
>>> print s
badcfe

答案 14 :(得分:0)

re.sub(r'(.)(.)',r"\2\1",'abcdef1234')

然而re有点慢。

def swap(s):
    i=iter(s)
    while True:
        a,b=next(i),next(i)
        yield b
        yield a

''.join(swap("abcdef1234"))

答案 15 :(得分:0)

像这样:

>>> s = "2143658709"
>>> ''.join([s[i+1] + s[i] for i in range(0, len(s), 2)])
'1234567890'

>>> s = "badcfe"
>>> ''.join([s[i+1] + s[i] for i in range(0, len(s), 2)])
'abcdef'

答案 16 :(得分:0)

你想要数字排序吗?或者你交换奇数/偶数索引数字?你的例子完全不清楚。

类别:

s = '2143'
p=list(s)
p.sort()
s = "".join(p)

现在是'1234'。诀窍在于list(string)将其分解为字符。

答案 17 :(得分:-1)

#Works on even/odd size strings
str = '2143657'
newStr = ''
for i in range(len(str)//2):
    newStr += str[i*2+1] + str[i*2]
if len(str)%2 != 0:
    newStr += str[-1]
print(newStr)

答案 18 :(得分:-1)

#Think about how index works with string in Python,
>>> a = "123456"
>>> a[::-1]
'654321'

答案 19 :(得分:-1)

从字符串交换前两个字符的最简单方法之一是

inputString = '2134'

extractChar = inputString[0:2]
swapExtractedChar = extractChar[::-1]          """Reverse the order of string"""
swapFirstTwoChar = swapExtractedChar + inputString[2:]
 
# swapFirstTwoChar = inputString[0:2][::-1] + inputString[2:]     """For one line code"""

print(swapFirstTwoChar)