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

42 投票
14 回答
25191 浏览
提问于 2025-04-16 16:51

假设你有这样一个字符串:

ABCDEFGH

你想把它反转,让它变成:

GHEFCDAB

那么,最有效或者说最符合Python风格的解决办法是什么呢?我试过几种不同的方法,但看起来都很糟糕……

提前谢谢你们!

更新

如果有人感兴趣的话,这不是作业。我有一个脚本在处理网络抓包的数据,并把它作为十六进制字节的字符串返回。问题是数据还是按照网络的顺序排列的。由于这个应用的写法,我不想再回去用像socket.htons这样的函数,我只想反转这个字符串。

不幸的是,我的尝试看起来太糟糕了,我知道一定有更好的方法(更符合Python风格的解决方案)——所以我在这里问这个问题。

14 个回答

14

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

编辑(第一次搞错了):

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,没能让你的代码正常工作!

15

有很多有趣的方法可以做到这一点

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

一个简单的方法是:

"".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']

然后把这些对反过来,最后再把结果拼接在一起。

撰写回答