Как присоединиться к списку целых чисел в один целочисленный питон

Akash Sharma спросил: 31 июля 2018 в 09:48 в: python

Учитывая список шестнадцатеричных целых чисел, я хочу получить одно шестнадцатеричное целое число, где целые числа рассматриваются как наиболее значимые и наименее значимые.

Например, данный ... [ 0x1A, 0xF3, 0x74, 0xA3]

... Я хочу закончить с помощью0x1AF374A3

На другом языке программирования, с которым я знаком, это довольно простая операция под названием "join ", но, по-видимому," join "означает что-то еще в Python.

Я знаю, что могу перебирать список, умножая каждый последующий элемент на 2 ^ и добавляя их. Я также знаю, что могу преобразовать элементы в строки, объединить их, а затем преобразовать обратно в целое. Но оба этих подхода кажутся неуклюжими. Похоже, что должен быть более простой / более элегантный способ. Есть ли?

Заранее благодарим за помощь!


6 ответов

Есть решение
duyue ответил: 31 июля 2018 в 04:04
from functools import reduce
reduce(lambda x, y: x<<8 | y, [0x1A, 0xF3, 0x74, 0xA3])
# 452162723
'0x{:X}'.format(452162723)
# '0x1AF374A3'

Обратное:

>>> [0x1AF374A3 >> i & 0xff for i in reversed(range(0, 32, 8))]
[26, 243, 116, 163]
>>> [hex(0x1AF374A3 >> i & 0xff) for i in reversed(range(0, 32, 8))]
['0x1a', '0xf3', '0x74', '0xa3']
Harsha B ответил: 31 июля 2018 в 11:20
Напишите некоторое описание, хотя код является описательным
Akash Sharma ответил: 31 июля 2018 в 12:35
Спасибо всем за комментарии. Я не знаю, как это решение сравнивает по производительности с остальными, но оно показалось самым элегантным, и кажется, что "Reduce" от "functools" в значительной степени специально создано для такого рода требований. Поэтому я буду использовать его. Одно небольшое изменение, которое я сделал: вместо "0x {: X}". Format (a) я использовал hex (a). Казалось, дать мне то же самое. Большое спасибо!!!
Akash Sharma ответил: 31 июля 2018 в 03:39
Еще раз спасибо, duyue! Это прекрасно работает! Есть ли элегантный способ сделать обратное? То есть я начинаю с 0x1AF374A3 и получаю [0x1A, 0xF3, 0x74, 0xA3]? Я искал в functools противоположность "уменьшить" (например, "увеличить", "расширить"), но не нашел ничего, что бросилось бы в меня.
duyue ответил: 31 июля 2018 в 03:59
@AkashSharma Не за что. Обратное можно сделать с помощью [0x1AF374A3 >> i & 0xff for i in reversed(range(0, 32, 8))]
Akash Sharma ответил: 31 июля 2018 в 04:46
Очень круто! Еще раз спасибо!
Laurent H. ответил: 31 июля 2018 в 11:35

Я предлагаю вам переключить значения на тип байты , чтобы объединить их, а затем переключиться обратно на тип int , как показано ниже:

myList = [0x1A, 0xF3, 0x74, 0xA3]
# Conversion to 'bytes'
a = bytes()
for b in myList:
    a += b.to_bytes(1,'big')
# Conversion back to 'int'
a = int.from_bytes(a, 'big')
print(hex(a))  # 0x1af374a3

И вы можете заменить классический цикл for на понимание генератора, передаваемое в качестве параметра методу join(), чтобы объединить байтовые элементы. Он по-прежнему читабелен и немного короче, как показано ниже:

myList = [0x1A, 0xF3, 0x74, 0xA3]
a = b''.join(b.to_bytes(1,'big') for b in myList) # Conversion to 'bytes'
a = int.from_bytes(a, 'big')                      # Conversion back to 'int'
print(hex(a))  # 0x1af374a3

Обратите внимание, что если целое число в списке ввода превышает 255, то логически вы получите ошибку OverflowError: int too big to convert из-за b.to_bytes(1,'big'). Конечно, это может быть улучшено путем управления исключением, если это может произойти.

Наконец, я могу также предложить вам решение, использующее умножение на степени 256, просто чтобы показать вам, что оно может быть достигнуто только в одна линия:

myList = [0x1A, 0xF3, 0x74, 0xA3]
a = sum(nb*(256**i) for i,nb in enumerate(reversed(myList)))
print(hex(a))  # 0x1af374a3
Dalen ответил: 31 июля 2018 в 10:41
+1 для умножения. Я просто писал это, когда ты украл мой ответ. : D Просто из любопытства. Что бы произошло в вашем методе bytes (), если целое число в списке превышает максимальный размер? : D
Laurent H. ответил: 31 июля 2018 в 11:01
Хорошо, если целое число в списке превышает 255, тогда вы логически получаете ошибку OverflowError: int too big to convert, потому что я считаю это неожиданным значением ввода. Конечно, это может быть улучшено путем управления исключением, если это может произойти.
Dalen ответил: 31 июля 2018 в 11:24
Точно так. Я только думал, что вы должны были обдумать это и упомянуть об этом в ответе.
Laurent H. ответил: 31 июля 2018 в 11:35
Я закончил свой ответ.
newbie ответил: 31 июля 2018 в 10:03
l = [0x1A, 0xF3, 0x74, 0xA3]merged = ''.join([str(hex(el))[2:] for el in l])

Если вам нужен гекс, вы можете получить его следующим образом:

hex(int(merged, 16)) --> 0x1af374a3
Dalen ответил: 31 июля 2018 в 10:52

В следующем коде нет ничего крайне неэффективного и уродливого, хотя это может показаться на первый взгляд. Если вам нужна еще большая скорость, вам придется использовать побитовые операторы для объединения всех целых чисел.

l = [0x1A, 0xF3, 0x74, 0xA3]
i = int("".join(hex(x)[2:] for x in l), 16)
# And to get the hex representation as requested:
print(hex(i).upper())

Есть еще один способ использовать плохие строки в этом, используя форматирование строк, подобное этому

i = int(len(l)*"%x" % tuple(l), 16)
print(hex(i))
E.Serra ответил: 31 июля 2018 в 09:57
mylist =[0x1A, 0xF3, 0x74, 0xA3]most_significant = str(hex(max(mylist)))
print(most_significant + ''.join([str(el).replace('0x', '') for el in mylist if el != max(mylist)]))
0xf326116163
Leon ответил: 31 июля 2018 в 04:13
Если я не ошибаюсь, ваш ответ не соответствует заданному вопросу. Вопрос состоял в том, чтобы объединить целые числа в порядке их появления в списке, а не с наибольшим числом впереди.
ikuamike ответил: 31 июля 2018 в 10:22

Вы можете преобразовать каждое в десятичное, затем обратно в шестнадцатеричное, но удалить 0x, объединить их вместе и затем добавить 0x в начале. format() хорошо справляется с такими преобразованиями.

mylist = [0x1A, 0xF3, 0x74, 0xA3]
result = '0x' + ''.join([format(int(n), 'x')for n in [format(i , 'd') for i in mylist]])

Вывод:

'0x1af374a3'