【问题标题】:How to join list of integers into one integer python如何将整数列表加入一个整数python
【发布时间】:2018-08-24 11:28:19
【问题描述】:

给定一个十六进制整数列表,我希望得到一个十六进制整数,其中整数被视为最重要的第一个,最不重要的最后一个。

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

...我想结束 0x1AF374A3

在我熟悉的另一种编程语言中,这是一个相当简单的操作,称为“join”,但显然“join”在 Python 中意味着其他东西。

我知道我可以遍历列表,将每个后续元素乘以 2^something 并将它们相加。我也知道我可以将元素转换为字符串,将它们连接起来,然后再转换回整数。但这两种方法似乎都很笨拙。似乎应该有一个更简单/更优雅的方式。有吗?

提前感谢您的帮助!

【问题讨论】:

  • 你可以做 str(max(list)) (将得到最重要的)。然后将其余部分作为字符串替换为 0x

标签: python list join integer byte


【解决方案1】:

我建议你将值切换为 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

您可以使用作为参数传递给join() 方法的生成器理解替换经典的 for 循环,以便连接字节项。还是可读的,短了一点,如下:

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,那么由于b.to_bytes(1,'big'),您在逻辑上会收到错误OverflowError: int too big to convert。当然,如果发生这种情况,可以通过管理异常来改进它。

我最后还可以建议你使用乘以 256 的幂的解决方案,只是为了告诉你它可以只用一行来实现:

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

【讨论】:

  • +1 表示乘法。当你偷了我的答案时,我正在写它。 :D 只是出于好奇。如果列表中的整数超过最大大小,您的 bytes() 方法会发生什么? :D
  • 如果列表中的整数超过 255,那么逻辑上您会收到错误 OverflowError: int too big to convert,因为我认为它是一个意外的输入值。当然,如果发生这种情况,可以通过管理异常来改进。
  • 正是如此。我只是认为您应该考虑一下并在答案中提及这一事实。
  • 我完成了我的回答。
【解决方案2】:
l = [0x1A, 0xF3, 0x74, 0xA3]

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

如果你需要十六进制,你可以得到它:

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

【讨论】:

    【解决方案3】:

    下面的代码并没有什么特别低效和丑陋的地方,虽然乍一看可能是这样。如果您需要更快的速度,您将不得不使用按位运算符将所有整数组合在一起。

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

    【讨论】:

      【解决方案4】:
      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']
      

      【讨论】:

      • 写一些描述,即使代码是描述性的
      • 感谢所有 cmets。我不知道这个解决方案在性能方面如何与其他解决方案进行比较,但它似乎是最优雅的,而且似乎“functools”中的“reduce”几乎是专门为这种需求而创建的。所以我会使用它。我做了一个小改动:我使用了 hex(a) 而不是 '0x{:X}'.format(a)。似乎给了我同样的东西。非常感谢!!!
      • 再次感谢度月!这很好用!现在有没有一种优雅的方式来做相反的事情?意思是我从 0x1AF374A3 开始,我得到 [0x1A, 0xF3, 0x74, 0xA3]?我在 functools 中查找了“减少”的反义词(例如“增强”、“扩展”),但没有发现任何让我大吃一惊的东西。
      • @AkashSharma 不客气。反过来可以[0x1AF374A3 &gt;&gt; i &amp; 0xff for i in reversed(range(0, 32, 8))]
      【解决方案5】:
      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

      【讨论】:

      • 如果我没记错的话,您的回答与所提出的问题不符。问题是按照它们在列表中出现的顺序组合整数,而不是前面的最大数字。
      【解决方案6】:

      您可以将每个转换为十进制,然后再转换回十六进制,但删除 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'
      

      【讨论】:

        【解决方案7】:

        我认为有一个干净的“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'
        

        如果列表中的最高有效字节位于列表末尾,请在int.from_bytes 函数中使用参数"little" 而不是"big"

        如果您的列表包含大于 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)
        

        【讨论】:

          猜你喜欢
          • 2023-03-10
          • 2022-08-02
          • 1970-01-01
          • 1970-01-01
          • 2020-06-07
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-07-04
          相关资源
          最近更新 更多