【问题标题】:Check whether a list of hexadecimal values is sequential or not检查十六进制值列表是否是连续的
【发布时间】:2015-05-07 06:30:28
【问题描述】:

想要一个函数/语句,检查mylist的所有值是否都是连续的,即十六进制列表。 例如:

def checkmylist(mylist):
    #code returns True or False


mylist1 = ['03', '04', '05', '06', '07', '08', '09', '0a', '0b', '0c','0d', '0e', '0f']
mylist2 = ['03', '05', '06', '07', '08', '09', '0a', '0b', '0c','0d', '0e', '0f']

checkmylist(mylist1)
#expected to returns pass
checkmylist(mylist2)
#expected to returns fail

【问题讨论】:

    标签: python list hex iteration sequence


    【解决方案1】:
    def checkmylist(mylist):
        it = (int(x, 16) for x in mylist)
        first = next(it)
        return all(a == b for a, b in enumerate(it, first + 1))
    

    在第一条语句中,我们将十六进制数转换为整数生成器。使用next(it),我们获取生成器的第一个元素。然后我们枚举从first + 1 开始编号的其余元素。如果每个元素的编号与元素本身相同,则我们得出结论,我们有一个顺序列表。

    【讨论】:

    • 感谢您的回答。 :)
    • 需要在上述函数中再添加一个逻辑,我的顺序会受到限制,例如00 to 1000 to 0a(Hex),有什么有效的方法可以做到这一点。我的函数也应该为mylist = ['00', '01', '02', '03', '04', '05', '06', '07', '08', '09', '0a','00', '01', '02', '03', '04', '05', '06', '07', '08', '09', '0a'] 返回true
    【解决方案2】:

    做到这一点的一个技巧是。这将查找列表中的总元素。正如您提到的,它不是连续的,最后一个元素的长度必须大于第一个元素。

    >>> def checkmylist(l):
    ...     a = [int(i,16) for i in sorted(set(l))]
    ...     return (len(a) == (a[-1]-a[0]+1))
    ... 
    >>> checkmylist(mylist1)
    True
    >>> checkmylist(mylist2)
    False
    >>> checkmylist(['2', '2', '4'])
    False
    

    【讨论】:

    • 你假设序列是有序的
    • @JuniorCompressor 在return语句前添加a.sort()!就这么简单。 (但是,OP 没有提到他需要那个)... :)
    • 那么 [2, 2, 4] 呢?它将返回 True。
    • @JuniorCompressor 这解决了您指出的两个缺陷!谢谢你:)
    • @JuniorCompressor:可以假设列表是有序的,因为如果不是,那么其中的元素不是连续的,因此添加的 sorted() 调用 Bhargav 并不是真正必要的——除此之外,它是对列表中的值进行错误排序(按字典顺序而不是数字:即sorted(['11', '20', '130']) 给出['11', '130', '20'])。
    【解决方案3】:

    您可以使用iter 创建列表的迭代器(从第二个索引到结尾),然后使用all 函数检查您是否有序列,请注意int(next(it),16)(或作为更有效的方式正如评论中提到的,使用functools.partial(int, base=16)) 会将您的字符串转换为基数为 16 的整数,然后您可以对它们进行操作:

    >>> import functools
    >>> int16 = functools.partial(int, base=16)
    >>> def checker(li):
    ...    it=iter(li[1:])
    ...    return all(int16(next(it))-int16(i)==1 for i in li[:-1])
    

    演示:

    mylist1 = ['03', '04', '05', '06', '07', '08', '09', '0a', '0b', '0c','0d', '0e', '0f']
    mylist2 = ['03', '05', '06', '07', '08', '09', '0a', '0b', '0c','0d', '0e', '0f']
    >>> checker(mylist1)
    True
    >>> checker(mylist2)
    False
    

    【讨论】:

    • 您可以通过使用int16 = functools.partial(int, base=16) 然后使用int16(x) 调用而不是int(x, 16) 来进一步优化这一点。
    • 我喜欢它可以适应 1 以外的增量
    【解决方案4】:
    mylist1 = ['03', '04', '05', '06', '07', '08', '09', '0a', '0b', '0c','0d', '0e', '0f']
    mylist2 = ['03', '05', '06', '07', '08', '09', '0a', '0b', '0c','0d', '0e', '0f']
    
    def checkmylist(li):
        start=int(li[0],16)
        for e in li[1:]:
            a=int(e,16)
            if a==start+1:
                start=a
            else:
                return False
        return True
    
    
    assert checkmylist(mylist1)==True
    #expected to returns pass
    assert checkmylist(mylist2)==False
    #expected to returns fail
    

    【讨论】:

      【解决方案5】:

      类似于@JuniorCompressor,但使用列表推导, 你的基本结构是:

      bool_match_to_myList = [1 if int(i, 16) else 0 for i in mylist]
      

      你可以很容易地检查它是否是真/假:

      myList_is_sequential = sum([1 if int(i, 16) else 0 for i in mylist]) < 1
      

      或者你可以在 numpy 的帮助下找到它关闭的索引(不是连续的)

      import numpy as np
      bool_match_to_myList_np = np.array([1 if int(i, 16) else 0 for i in mylist])
      np.where(bool_match_to_myList == 0)[0]
      

      【讨论】:

        【解决方案6】:

        另一种选择,利用 Pandas 的“力量”:

        def is_sequential(mylist):
            serie = pd.Series(mylist).apply(lambda x: int(x,16))
            return (serie.diff() > 1).sum() == 0
        
        • 将 mylist 变量转换为 int 系列
        • 使用 diff() 函数,获取上一个值和当前值之间的差异
        • 对所有大于 1 的值求和(我们想要的步骤),因此如果 sum() 等于 0,则所有值都是连续的
        is_sequential(mylist1) # returns True
        is_sequential(mylist2) # returns False
        

        【讨论】:

        • 不错!为了使其更健壮并包括 [1,2,3,0] 之类的情况(其中 diff 将在末尾显示 -3 并且将失败 "> 1" 条件),您需要在 diff 之后添加 abs() ():return (serie.diff().abs() &gt; 1).sum() == 0
        猜你喜欢
        • 2018-06-27
        • 2012-07-20
        • 1970-01-01
        • 1970-01-01
        • 2014-11-14
        • 2023-03-19
        • 2013-01-13
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多