如何在十六进制字符串中交换相邻字节(使用或不使用正则表达式)

2 投票
6 回答
3961 浏览
提问于 2025-04-15 18:11

给定一个字符串(或者任何长度的字符串,只要它的单词对数是偶数):

"12345678"

我想知道怎么交换相邻的“单词”?

我想要的结果是:

"34127856"

而且,当这个操作完成后,我还需要交换长的部分。

我想要的最终结果是:

"78563412"

6 个回答

1

这里是针对字符串 "12345678" 的内容。

from textwrap import wrap
s="12345678"
t=wrap(s,len(s)/2)
a,b=wrap(t[0],len(t[0])/2)
c,d=wrap(t[1],len(t[1])/2)
a,b=b,a
c,d=d,c
print a+b+c+d

你可以把它做成一个通用的函数,这样就可以处理不同长度的字符串了。

输出结果

$ ./python.py
34127856
3

在编程中,有时候我们需要处理一些数据或者信息,这时候就会用到“数据结构”。简单来说,数据结构就是用来组织和存储数据的一种方式。想象一下,如果你有很多书,想要把它们放在一个书架上,你可能会按照作者的名字、书的类型或者出版日期来分类,这就是一种数据结构的应用。

在编程里,常见的数据结构有数组、链表、栈、队列、树和图等。每种数据结构都有自己的特点和适用场景。例如,数组就像一个整齐的书架,书本按顺序排列,查找某本书很方便;而链表则像一串珠子,每颗珠子都指向下一颗,适合频繁插入和删除的情况。

了解这些数据结构可以帮助你更有效地管理和操作数据,让你的程序运行得更快、更顺畅。

import re
re.sub(r'(..)(..)', r'\2\1', '12345678')
re.sub(r'(....)(....)', r'\2\1', '34127856')
5

这里介绍了一种使用正则表达式的方法:

import re
twopairs = re.compile(r'(..)(..)')
stringwithswappedwords = twopairs.sub(r'\2\1', basestring)
twoquads = re.compile(r'(....)(....)')
stringwithswappedlongs = twoquads.sub(r'\2\1', stringwithswappedwords)

补充说明:不过,这绝对不是在Python中最快的方法——那么我们怎么知道这些呢?首先,把所有“竞争”的方法写到一个模块里,这里我叫它 'swa.py'……:

import re

twopairs = re.compile(r'(..)(..)')
twoquads = re.compile(r'(....)(....)')

def withre(basestring, twopairs=twopairs, twoquads=twoquads):
  stringwithswappedwords = twopairs.sub(r'\2\1', basestring)
  return twoquads.sub(r'\2\1', stringwithswappedwords)

def withoutre(basestring):
  asalist = list(basestring)
  asalist.reverse()
  for i in range(0, len(asalist), 2):
    asalist[i+1], asalist[i] = asalist[i], asalist[i+1]
  return ''.join(asalist)

s = '12345678'
print withre(s)
print withoutre(s)

注意我设置了 s,并尝试这两种方法,快速检查一下它们是否计算出相同的结果——对于这种“性能对比赛”,这样做是个好习惯!

然后,在命令行中,你可以使用 timeit,方法如下:

$ python -mtimeit -s'import swa' 'swa.withre(swa.s)'
78563412
78563412
10000 loops, best of 3: 42.2 usec per loop
$ python -mtimeit -s'import swa' 'swa.withoutre(swa.s)'
78563412
78563412
100000 loops, best of 3: 9.84 usec per loop

……这样你就会发现,在这种情况下,不使用正则表达式的方法大约快4倍,这样的优化是很有价值的。一旦你有了这样的“测量工具”,如果需要“真正的超快速度”,也可以轻松尝试其他替代方案和调整。

补充说明:例如,这里有一个更快的方法(添加到同一个 swa.py 中,最后一行当然是 print faster(s);-):

def faster(basestring):
  asal = [basestring[i:i+2]
          for i in range(0, len(basestring), 2)]
  asal.reverse()
  return ''.join(asal)

这样得到:

$ python -mtimeit -s'import swa' 'swa.faster(swa.s)'
78563412
78563412
78563412
100000 loops, best of 3: 5.58 usec per loop

大约5.6微秒,比最简单的不使用正则表达式的方法的9.8微秒要快,是另一个可能值得的微优化。

当然,这样的优化还有很多——有个老话(伪定理)说,任何程序都可以缩短至少一个字节,并且至少快一纳秒……;-)

补充说明:为了“证明”这个伪定理,这里有一个完全不同的方法(替换掉 swa.py 的结尾)……:

import array
def witharray(basestring):
  a2 = array.array('H', basestring)
  a2.reverse()
  return a2.tostring()

s = '12345678'
# print withre(s)
# print withoutre(s)
print faster(s)
print witharray(s)

这样得到:

$ python -mtimeit -s'import swa' 'swa.witharray(swa.s)'
78563412
78563412
100000 loops, best of 3: 3.01 usec per loop

可能会有进一步值得的加速。

撰写回答