简体   繁体   English

如何将整数列表加入一个整数python

[英]How to join list of integers into one integer python

Given a list of hex integers, I want to end up with one hex integer where the integers are treated as most-significant first and least-significant last.给定一个十六进制整数列表,我想以一个十六进制整数结束,其中整数被视为最重要的第一个和最不重要的最后一个。

For example, given... [0x1A, 0xF3, 0x74, 0xA3]例如,给定... [0x1A, 0xF3, 0x74, 0xA3]

...I want to end up with 0x1AF374A3 ...我想以 0x1AF374A3 结尾

In another programming language that I'm familiar with this is a fairly simple operation called "join", but apparently "join" means something else in Python.在我熟悉的另一种编程语言中,这是一个相当简单的操作,称为“连接”,但显然“连接”在 Python 中有其他含义。

I know I can iterate through the list multiplying each subsequent element by 2^something and adding them.我知道我可以遍历列表,将每个后续元素乘以 2^something 并将它们相加。 I also know I can convert the elements to strings, concatenate them and then convert back to integer.我也知道我可以将元素转换为字符串,连接它们,然后再转换回整数。 But both those approaches seem clunky.但这两种方法似乎都很笨拙。 Seems like there should be a simpler / more elegant way.似乎应该有一种更简单/更优雅的方式。 Is there?在那儿?

Thanks in advance for any help!在此先感谢您的帮助!

I suggest you to switch the values to bytes type in order to concatenate them, them switch back to int type, as follows:我建议您将值切换为bytes类型以便将它们连接起来,它们切换回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

And you can replace the classic for loop with a generator comprehension passed as parameter to join() method, in order to concatenate the bytes items.您可以将经典的 for 循环替换为作为参数传递给join()方法的生成器理解,以便连接字节项。 It is still readable and a bit shorter, as follows:它仍然是可读的,并且更短一些,如下所示:

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

Note that if an integer in the input list exceeds 255, then you logically get the error OverflowError: int too big to convert due to b.to_bytes(1,'big') .请注意,如果输入列表中的整数超过 255,那么逻辑上您会收到错误OverflowError: int too big to convert due to b.to_bytes(1,'big') Of course it can be improved by managing the exception if this case can happen.当然,如果这种情况发生,可以通过管理异常来改进。

I finally may also suggest you the solution using the multiplication by powers of 256, just to show you that it can be achieved in only one-line:最后,我可能还会建议您使用 256 的幂乘法的解决方案,只是为了向您展示它可以仅在一行中实现:

myList = [0x1A, 0xF3, 0x74, 0xA3]
a = sum(nb*(256**i) for i,nb in enumerate(reversed(myList)))
print(hex(a))  # 0x1af374a3
l = [0x1A, 0xF3, 0x74, 0xA3]

merged = ''.join([str(hex(el))[2:] for el in l])

If you need the hex you can get it as:如果你需要十六进制,你可以得到它:

hex(int(merged, 16)) --> 0x1af374a3

There is nothing extremely inefficient nor ugly in the following code, although it may seem so at a first glance.以下代码中没有任何极度低效或丑陋的地方,尽管乍一看可能如此。 If you need even more speed you will have to use bitwise operators to jam all ints together.如果您需要更快的速度,则必须使用按位运算符将所有整数组合在一起。

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())

There is another way to exploit poor strings in this by using the string formatting like this:还有另一种方法可以通过使用如下字符串格式来利用其中的不良字符串:

i = int(len(l)*"%x" % tuple(l), 16)
print(hex(i))
from functools import reduce
reduce(lambda x, y: x<<8 | y, [0x1A, 0xF3, 0x74, 0xA3])
# 452162723
'0x{:X}'.format(452162723)
# '0x1AF374A3'

The reverse:相反:

>>> [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']
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 0xf326116163

You can convert each to decimal then back to hex but remove the 0x, the join them together and then add 0x at the beginning.您可以将每个转换为十进制,然后再转换回十六进制,但删除 0x,将它们连接在一起,然后在开头添加 0x。 format() is good at doing such conversions. format()擅长做这样的转换。

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

Output:输出:

'0x1af374a3'

I think there is a clean and "pythonic" way to solve this, using the Python bytearray type:我认为有一种干净且“pythonic”的方法可以使用 Python bytearray类型来解决这个问题:

foolist = [0x1A, 0xF3, 0x74, 0xA3]
# convert to bytearray and then to a single integer in one line:
x = int.from_bytes(bytearray(foolist), "big")
print(hex(x))
# '0x1af374a3'

In case the most significant byte in the list is at the end of the list, use the parameter "little" instead of "big" in the int.from_bytes function.如果列表中最重要的字节位于列表末尾,请在int.from_bytes函数中使用参数"little"而不是"big"

In case your list contains an integer bigger than 255, ValueError exception will be raised:如果您的列表包含大于 255 的整数,将引发ValueError异常:

>>> foolist1 = [0xFF, 255]                                                                                 

>>> bytearray(foolist1)                                                                                    
bytearray(b'\xff\xff')


>>> foolist2 = [0xFF, 256]                                                                                 

>>> bytearray(foolist2)                                                                                    
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: byte must be in range(0, 256)

byte must be in range(0, 256)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM