结合位标志

5

我有几个标记:

    None = 0
    HR = 1
    HD = 2,
    DT = 4,
    Fl = 8
..

我想创建一个函数,输入一个特定的标志,比如:6。
返回的应该是HDDT,因为2 | 4 = 6。 也可能组合3个或更多的标志,或只有一个。 例如:7 = 1 | 2 | 4 => HRHDDT。
如何根据标志值返回连接的字符串?
在我的情况下,枚举有更多的条目,这将使简单的if语句非常不舒适,因为我必须覆盖数百种情况。
有没有什么聪明的解决方案?

1
标志位是如何存储的? - Willem Van Onsem
我还没有存储它们 - 我知道这些值,但是我不确定将它们集成的最佳方式是什么。直接在if语句中,通过创建某种枚举类型..? - Kyu96
我会使用字典。 - t.m.adam
输入0的逻辑答案应该是空字符串,对吗? - Davis Herring
2个回答

3

假设我们有一个包含二的幂次方的列表:

flags = ['HR','HD','DT','Fl']

然后您可以编写以下函数:
def power2():
    i = 1
    while True:
        yield i
        i *= 2

def obtain_flag(val):
    if val:
        return ''.join([f for f,i in zip(flags,power2()) if i&val])
    else:
        return None

return None是不必要的:它是映射到零的标志。

或者,如果你想要一个标志列表(在这种情况下,标志可以是任何内容):

def obtain_flag(val):
    if val:
        return [f for f,i in zip(flags,power2()) if i&val]

这将会得到:
>>> obtain_flag(6)
'HDDT'
>>> obtain_flag(7)
'HRHDDT'
>>> obtain_flag(0) # returns None, but None is not printed
>>> obtain_flag(1)
'HR'
>>> obtain_flag(2)
'HD'
>>> obtain_flag(3)
'HRHD'
>>> obtain_flag(4)
'DT'

为什么不使用 enumerate1<<n 来避免需要 power2 辅助函数呢? - Davis Herring

1
您可以将标记存储为类似于dict的形式:
flags = {1:'HR', 2:'HD', 4:'DT', 8:'FL'}

通过位运算符 and 按位与您的数字和标志以检索字符串:

def get_flags(num):
    if num:
        return ''.join(flags[x] for x in flags if x & num)
    return None

>>> get_flags(6)
'HDDT'

return None 这一行是多余的,但仍然+1。 - t.m.adam
这正是我正在寻找的^^ - Kyu96

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接