在Python中反转一个字符串两个字符(网络字节顺序)

时间:2011-05-03 01:48:54

标签: python string reverse

说你有这个字符串:

ABCDEFGH

你要反转它,以便它变成:

GHEFCDAB

什么是最有效/ pythonic的解决方案?我尝试了一些不同的东西,但它们看起来都很糟糕......

提前致谢!

更新

如果有人感兴趣,这不是作业。我有一个脚本处理来自网络捕获的数据并将其作为一个十六进制字节字符串返回。问题是数据仍处于网络状态。由于应用程序的编写方式,我不想回过头来尝试使用say socket.htons,我只是想反转字符串。

不幸的是,我的尝试看起来很可怕,我知道必须有一个更好的方法(一个更加pythonic的解决方案) - 因此我的问题在这里。

14 个答案:

答案 0 :(得分:30)

这样做的简洁方法是:

"".join(reversed([a[i:i+2] for i in range(0, len(a), 2)]))

首先将字符串分成几对:

>>> [a[i:i+2] for i in range(0, len(a), 2)]
['AB', 'CD', 'EF', 'GH']

然后将其反转,最后将结果重新连接起来。

答案 1 :(得分:14)

很多有趣的方法

>>> s="ABCDEFGH"
>>> "".join(map(str.__add__, s[-2::-2] ,s[-1::-2]))
'GHEFCDAB'

答案 2 :(得分:10)

如果有人感兴趣,这是所有答案的时间。

编辑(第一次弄错了):

import timeit
import struct

string = "ABCDEFGH"

# Expected resutlt => GHEFCDAB

def rev(a):
    new = ""

    for x in range(-1, -len(a), -2):
        new += a[x-1] + a[x]

    return new

def rev2(a):
    return "".join(reversed([a[i:i+2] for i in range(0, len(a), 2)]))

def rev3(a):
    return "".join(map(str.__add__, a[-2::-2] ,a[-1::-2]))

def rev4(a):
    return "".join(map("".join, reversed(zip(*[iter(a)]*2))))


def rev5(a):
    n = len(a) / 2
    fmt = '%dh' % n
    return struct.pack(fmt, *reversed(struct.unpack(fmt, a)))

def rev6(a):
    return "".join([a[x:x+2] for x in range(0,len(a),2)][::-1])


print "Greg Hewgill %f" %timeit.Timer("rev2(string)", "from __main__ import rev2, string").timeit(100000)
print "gnibbler %f" %timeit.Timer("rev3(string)", "from __main__ import rev3, string").timeit(100000)
print "gnibbler second %f" %timeit.Timer("rev4(string)", "from __main__ import rev4, string").timeit(100000)
print "Alok %f" %timeit.Timer("rev5(string)", "from __main__ import rev5, struct, string").timeit(100000)
print "elliot42 %f" %timeit.Timer("rev6(string)", "from __main__ import rev6, struct, string").timeit(100000)
print "me %f" %timeit.Timer("rev(string)", "from __main__ import rev, string").timeit(100000)

string = "ABCDEFGH"的结果:

Greg Hewgill 0.853000
gnibbler 0.428000
gnibbler second 0.707000
Alok 0.763000
elliot42 0.237000
me 0.200000

string = "ABCDEFGH"*5的结果:

Greg Hewgill 2.246000
gnibbler 0.811000
gnibbler second 1.205000
Alok 0.972000
elliot42 0.594000
me 0.584000

string = "ABCDEFGH"*10的结果:

Greg Hewgill 2.058000
gnibbler 1.178000
gnibbler second 1.926000
Alok 1.210000
elliot42 0.935000
me 1.082000

string = "ABCDEFGH"*100的结果:

Greg Hewgill 9.762000
gnibbler 9.134000
gnibbler second 14.782000
Alok 5.775000
elliot42 7.351000
me 18.140000

*对不起@Lacrymology无法让你工作!

答案 3 :(得分:6)

>>> import array
>>> s="abcdef"
>>> a=array.array('H',s)
>>> a.byteswap()
>>> a.tostring()
'badcfe'

如果要交换元素顺序而不是字节顺序,请使用a.reverse()而不是a.byteswap()来完成。

我冒昧地编辑了Trufa的基准脚本。 modified script生成graphical plot,显示所有函数的近似线性缩放。

答案 4 :(得分:4)

这是一般形式。分组的大小可以很容易地一次更改为不同的字符数。字符串长度应该是分组大小的精确倍数

>>> "".join(map("".join, reversed(zip(*[iter("ABCDEFGH")]*2))))
'GHEFCDAB'

(这是Python 2,它在3中不起作用)

答案 5 :(得分:3)

您可以使用此功能,但不要告诉任何人我编写此代码: - )

import struct

def pair_reverse(s):
    n = len(s) / 2
    fmt = '%dh' % n
    return struct.pack(fmt, *reversed(struct.unpack(fmt, s)))

pair_reverse('ABCDEFGH')

答案 6 :(得分:3)

st = "ABCDEFGH"
"".join([st[x:x+2] for x in range(0,len(st),2)][::-1])
编辑:诅咒,显然比另一张海报慢27分钟。但我更喜欢反向切片符号。

有关反向切片的更多信息,请访问:"".join(reversed(val)) vs val[::-1]...which is pythonic?

答案 7 :(得分:1)

我的朋友Rob指出了一个漂亮的递归解决方案:

def f(s):
    return "" if not s else f(s[2:]) + s[:2]

答案 8 :(得分:0)

只需一枪

st = "ABCDEFGH"
s = [st[2*n:2*n+1] for n in range(len(st)/2)]
return s[::-1].join('')

这假设len(st)是偶数,否则将其改为范围(len(st)/ 2 + 1),我甚至确定有更好的方法将其分成两个。

如果你的python抱怨s [:: - 1]你可以使用reverse(s)

答案 9 :(得分:0)

还有另一种方式:

a = "ABCDEFGH"
new = ""

for x in range(-1, -len(a), -2):
    new += a[x-1] + a[x]

print new

答案 10 :(得分:0)

这看起来像是家庭作业。所以这是一个非常非传统的方法,你可能会感兴趣:

>>> s = "ABCDEFGH"
>>> ''.join([s[::2][::-1][i]+s[::-2][i] for i in range(len(s[::2]))])
'GHEFCDAB'

祝你好运!

答案 11 :(得分:0)

而另一个人继续...

>>> rev = "ABCDEFGH"[::-1]
>>> ''.join([''.join(el) for el in zip(rev[1::2], rev[0::2])])
'GHEFCDAB'

答案 12 :(得分:0)

我最喜欢这种解决方案,因为它是最简单,最整洁的:

import struct
hex = struct.pack('<I', 0x41424344) #ABCD
print(hex) # BCDA

答案 13 :(得分:0)

这里是一个函数,该函数基于上面的最佳,最快和最Pythonic答案,并使用当前的Python 3语法:

def reverse_hex(hex_string):
    if isinstance(hex_string, str):
        input_is_string = True
        hex_string = hex_string.encode()
    a = array.array('H', hex_string)
    a.reverse()
    output = a.tobytes()
    if input_is_string:
        return output.decode()
    else:
        return output