2017-12-07 4 views
3

値が(列挙型またはオブジェクト型の)フラグのセットに対応するかどうかを確認したいと思います。値が列挙型の複数の特定のフラグと一致するかどうかを検証する(ビット単位で)

今、私は(スニペットを賞賛:3):JavaScriptで以下の機能が出ている

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

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の両方のソリューションは高く評価されていますが、特に私はウェブ上で多くの検索をしていて、決して見つからなかったアルゴリズムを探しています。それは共通の問題です。

+0

さらに多くのpythonicを意味しますか?これは私にとっては大丈夫です。たぶん私は間違っています。 – scharette

答えて

0

条件が間違っていると終了するArray#everyで確認できます。 Pythonで

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
.as-console-wrapper { max-height: 100% !important; top: 0; }

+0

私は、JSではなくPythonについて質問していると思います。 –

+0

@pycoder、それはJSの答えが有効であるように見えます。 –

0

1つのオプションは、フラグがenumモジュールから(例えば)列挙の要素であるフラグのsetあります。これはサブセット演算子の利点が既に定義されているので、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 
... 
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 
# ... 
関連する問題