【发布时间】:2011-06-04 01:49:07
【问题描述】:
我想交换字符串中的每一对字符。 '2143' 变为 '1234','badcfe' 变为 'abcdef'。
如何在 Python 中做到这一点?
【问题讨论】:
我想交换字符串中的每一对字符。 '2143' 变为 '1234','badcfe' 变为 'abcdef'。
如何在 Python 中做到这一点?
【问题讨论】:
这是一种方法...
>>> 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 = '2143'
p=list(s)
p.sort()
s = "".join(p)
s 现在是“1234”。诀窍在于 list(string) 将其分解为字符。
【讨论】:
''.join(sorted(s)) 会更简洁,并且同样清晰。
循环遍历字符串的长度并交换:
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 异常。
【讨论】:
在 Python 中交换两个项目的常用方法是:
a, b = b, a
所以在我看来,你会用扩展切片做同样的事情。但是,它有点复杂,因为字符串是不可变的。所以您必须先转换为列表,然后再转换回字符串。
因此,我会做以下事情:
>>> s = 'badcfe'
>>> t = list(s)
>>> t[::2], t[1::2] = t[1::2], t[::2]
>>> ''.join(t)
'abcdef'
【讨论】:
''.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 上运行。
【讨论】:
IndexError: string index out of range,第二个印最后一个字符。
像这样:
>>> 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'
【讨论】:
单线:
>>> s = 'badcfe'
>>> ''.join([ s[x:x+2][::-1] for x in range(0, len(s), 2) ])
'abcdef'
【讨论】:
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"))
【讨论】:
如果性能或优雅不是问题,并且您只想要清晰并完成工作,那么只需使用这个:
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
【讨论】:
没有必要列出清单。以下适用于偶数长度的字符串:
r = ''
for in in range(0, len(s), 2) :
r += s[i + 1] + s[i]
s = r
【讨论】:
另一种方式:
>>> s='123456'
>>> ''.join([''.join(el) for el in zip(s[1::2], s[0::2])])
'214365'
【讨论】:
>>> 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
【讨论】:
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
【讨论】:
#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)
【讨论】:
#Think about how index works with string in Python,
>>> a = "123456"
>>> a[::-1]
'654321'
【讨论】:
更一般的答案...您可以使用这种方法对元组或字符串进行任何单对交换:
# 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 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))
基本上是单线,不需要超出索引范围的任何迭代器,以及一些非常简单的整数数学。
【讨论】:
从字符串中交换前两个字符的最简单方法之一是
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)
【讨论】:
虽然上述解决方案确实有效,但我们可以用“外行”的话来说,有一个非常简单的解决方案。仍在学习 python 和字符串的人可以使用其他答案,但他们并不真正了解它们的工作原理或代码的每个部分在做什么,而没有海报的完整解释而不是“这有效”。下面执行字符串中每隔一个字符的交换,对于初学者来说很容易理解它是如何工作的。
它只是简单地迭代字符串(任何长度)(从 0 开始并找到每个第二个字符),然后通过添加当前索引 + 1(第二个字符)然后实际创建一个新字符串(swapped_pair)索引(第一个字符),例如,索引 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
【讨论】:
交换位置为 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"
【讨论】: