Реверс строки в Python два символа за раз (порядок байтов сети)
скажем, у вас есть эта строка:
ABCDEFGH
и вы хотите изменить его так, чтобы он стал:
GHEFCDAB
что бы быть наиболее эффективным / подходящие для Python решение? Я пробовал несколько разных вещей, но все они выглядят ужасно...
спасибо заранее!
обновление:
в случае, если кто-то заинтересован, это было не для домашней работы. У меня был скрипт, который обрабатывал данные из сетевого захвата и возвращал их как строка шестнадцатеричных байтов. Проблема была данные еще в сетевом порядке. Из-за того, как было написано приложение, я не хотел возвращаться и пытаться использовать say socket.htons, я просто хотел обратного строку.
12 ответов
краткий способ сделать это:
"".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']
затем обратить это вспять и, наконец, объединить результат вместе.
много интересных способов сделать это
>>> s="ABCDEFGH"
>>> "".join(map(str.__add__, s[-2::-2] ,s[-1::-2]))
'GHEFCDAB'
если кто-то заинтересован, это время для всех* ответы.
EDIT (ошибся в первый раз):
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 не может сделать вашу работу!
>>> import array
>>> s="abcdef"
>>> a=array.array('H',s)
>>> a.byteswap()
>>> a.tostring()
'badcfe'
завершить с помощью a.reverse () вместо a.byteswap (), если вы хотите поменять порядок элементов, а не порядок байтов.
Я взял на себя смелость немного отредактировать тестовый скрипт Trufa. The изменен скрипт создан графический участка отображение приблизительно линейного масштабирования для всех функций.
вот общая форма. Размер группировки можно легко изменить на другое количество символов за раз. Длина строки должна быть точной кратной размеру группировки
>>> "".join(map("".join, reversed(zip(*[iter("ABCDEFGH")]*2))))
'GHEFCDAB'
(Это Python 2, он не будет работать в 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')
st = "ABCDEFGH"
"".join([st[x:x+2] for x in range(0,len(st),2)][::-1])
EDIT: проклятия, по-видимому, на 27 минут медленнее, чем другой плакат. Но мне больше нравится нотация обратного среза.
дополнительная информация об обратном срезе здесь:"".join(reversed (val)) vs val[::-1]...что такое питон?
мой друг Роб указал на красивое рекурсивное решение:
def f(s):
return "" if not s else f(s[2:]) + s[:2]
просто удар
st = "ABCDEFGH"
s = [st[2*n:2*n+1] for n in range(len(st)/2)]
return s[::-1].join('')
это предполагает, что len(st) четный, в противном случае измените это на range(len(st)/2+1), и я даже уверен, что есть лучший способ сделать это разделить на двойки.
Если ваш python жалуется на s [:: -1] вы можете использовать reversed(s)
и еще один способ:
a = "ABCDEFGH"
new = ""
for x in range(-1, -len(a), -2):
new += a[x-1] + a[x]
print new
это похоже на домашнюю работу. Итак, вот очень неортодоксальный подход, который может вас заинтересовать:
>>> s = "ABCDEFGH"
>>> ''.join([s[::2][::-1][i]+s[::-2][i] for i in range(len(s[::2]))])
'GHEFCDAB'
Удачи!
и еще попадет...
>>> rev = "ABCDEFGH"[::-1]
>>> ''.join([''.join(el) for el in zip(rev[1::2], rev[0::2])])
'GHEFCDAB'