验证(按位)值是否与枚举的多个特定标志匹配

时间:2017-12-07 21:27:21

标签: javascript python enums bitwise-operators

我想检查一个值是否对应于一组标志(来自枚举或对象)。

现在,我已经在javascript中提出了以下功能(赞美代码段:3):



function hasFlags(flags, value) {
    let s = flags.reduce((sum, v) => sum += v, 0);
    
    return (s & value) === s
}

FLAGS = {
    STEP_0: 1 << 0,
    STEP_1: 1 << 1,
    STEP_2: 1 << 2,
    STEP_3: 1 << 3,
    STEP_4: 1 << 4,
    STEP_5: 1 << 5,
    STEP_6: 1 << 6,
    STEP_7: 1 << 7
}

const needed = [
    FLAGS.STEP_2,
    FLAGS.STEP_3,
    FLAGS.STEP_6,
]

console.log(hasFlags(needed, 4));                  // false
console.log(hasFlags(needed, 8));                  // false
console.log(hasFlags(needed, 64));                 // false
console.log(hasFlags(needed, 4 + 8));              // false
console.log(hasFlags(needed, 4 + 64));             // false
console.log(hasFlags(needed, 8 + 64));             // false
console.log(hasFlags(needed, 4 + 8 + 64));         // true
console.log(hasFlags(needed, 4 + 8 + 64 + 1));     // true
console.log(hasFlags(needed, 4 + 8 + 64 + 2));     // true
console.log(hasFlags(needed, 4 + 8 + 64 + 1 + 2)); // true
// etc...
&#13;
&#13;
&#13;

在python中,函数看起来像这样:

def hasFlags(flags, value):
    s = sum(flags)
    return (s & value) == s

print hasFlags((4,8,64), 4)  # False
print hasFlags((4,8,64), 4+8+64)  # True
# ...

有没有更好的方法(也就是更多惯用...或更多pythonic)来做同样的验证?

编辑:python和javascript中的解决方案都很受欢迎,但我特别想找到一种算法(无论语言是什么),因为我在网上搜索过很多但从未找到任何算法,而在我看来这是一个常见的问题。

3 个答案:

答案 0 :(得分:0)

您可以查看Array#every,如果条件错误则退出。

operator []
const
    hasFlags = (flags, value) => flags.every(flag => flag & value),
    FLAGS = {
        STEP_0: 1 << 0,
        STEP_1: 1 << 1,
        STEP_2: 1 << 2,
        STEP_3: 1 << 3,
        STEP_4: 1 << 4,
        STEP_5: 1 << 5,
        STEP_6: 1 << 6,
        STEP_7: 1 << 7
    },
    needed = [
        FLAGS.STEP_2,
        FLAGS.STEP_3,
        FLAGS.STEP_6,
    ];

console.log(hasFlags(needed, 4));                  // false
console.log(hasFlags(needed, 8));                  // false
console.log(hasFlags(needed, 64));                 // false
console.log(hasFlags(needed, 4 + 8));              // false
console.log(hasFlags(needed, 4 + 64));             // false
console.log(hasFlags(needed, 8 + 64));             // false
console.log(hasFlags(needed, 4 + 8 + 64));         // true
console.log(hasFlags(needed, 4 + 8 + 64 + 1));     // true
console.log(hasFlags(needed, 4 + 8 + 64 + 2));     // true
console.log(hasFlags(needed, 4 + 8 + 64 + 1 + 2)); // true

答案 1 :(得分:0)

Python中的一个选项是set个标志,其中flags是(例如)来自enum模块的枚举的元素。这也有已经定义的子集运算符的好处,因此您可以执行needed <= flags

您的最终代码如下所示:

from enum import Enum

class Flags(enum.Enum):
  flag0 = {0}
  flag1 = {1}
  flag2 = {2}
  ...

def has_flags(needed, flags):
  return needed <= flags

needed = Flags.flag2 | 
         Flags.flag3 |
         Flags.flag6

print(has_flags(needed, Flags.flag2)) #false
print(has_flags(needed, Flags.flag3)) #false
...

答案 2 :(得分:0)

当标志组合表示为位掩码时,您可以使用逐位运算符直接对所有标志进行突变和测试。

STEP_0 = 1 << 0
STEP_1 = 1 << 1
STEP_2 = 1 << 2
STEP_3 = 1 << 3
STEP_4 = 1 << 4
STEP_5 = 1 << 5
STEP_6 = 1 << 6
STEP_7 = 1 << 7

def has_flags(flags_to_check_for, cur_flags):
    return (cur_flags & flags_to_check_for) == flags_to_check_for

desired_flags = STEP_2 | STEP_3 | STEP_6 

cur_flags = STEP_2
print has_flags(desired_flags, cur_flags)   # False
cur_flags |= STEP_3
cur_flags |= STEP_6
print has_flags(desired_flags, cur_flags)  # True
# ...