1. ホーム
  2. c#

[解決済み] 複数のブーリアンが "true "であるかどうかをエレガントに判定する。

2023-06-04 18:01:04

質問

5つのブーリアン値のセットがある。これらのうちの1つ以上が真である場合、私は特定の関数を実行したいと思います。単一のif()文でこの条件をチェックすることを可能にする、あなたが考えることができる最もエレガントな方法は何ですか?ターゲット言語はC#ですが、私は他の言語でのソリューションにも興味があります(特定の組み込み関数について話していない限りにおいて)。

1つの興味深いオプションは、バイトにブール値を格納し、右シフトを行い、元のバイトと比較することです。次のようなものです。 if(myByte && (myByte >> 1)) しかし、これは個別のブール値をバイトに変換する必要があり (bitArray を介して?) 、少し (ダジャレで) 不器用な感じがします...。 [edit]すみません、これは次のようになるはずでした。 if(myByte & (myByte - 1)) [/edit]です。

注:これはもちろん古典的なquot;population count", "sideways addition" or "Hamming weight" programming problemに非常に近いですが、全く同じというわけではありません。私はビットがいくつセットされているか知る必要はなく、複数セットされていればいいのです。私の希望は、これを達成するためにもっと簡単な方法があることです。

どのように解決するのですか?

どのように

  if ((bool1? 1:0) + (bool2? 1:0) + (bool3? 1:0) + 
      (bool4? 1:0) + (bool5? 1:0) > 1)
      // do something

とか一般化された方法なら

   public bool ExceedsThreshold(int threshold, IEnumerable<bool> bools)
    {
       int trueCnt = 0;
       foreach(bool b in bools)
          if (b && (++trueCnt > threshold)) 
              return true;
       return false;          
    } 

または、他の回答で提案されているようにLINQを使用します。

    public bool ExceedsThreshold(int threshold, IEnumerable<bool> bools)
    { return bools.Count(b => b) > threshold; }

EDIT (Joel Coehoornの提案を追加する。 (.Net 2.x およびそれ以降で)

    public void ExceedsThreshold<T>(int threshold, 
                      Action<T> action, T parameter, 
                      IEnumerable<bool> bools)
    { if (ExceedsThreshold(threshold, bools)) action(parameter); }

または.Net 3.5以降で使用できます。

    public void ExceedsThreshold(int threshold, 
            Action action, IEnumerable<bool> bools)
    { if (ExceedsThreshold(threshold, bools)) action(); }

の拡張として、あるいは IEnumerable<bool>

  public static class IEnumerableExtensions
  {
      public static bool ExceedsThreshold<T> 
         (this IEnumerable<bool> bools, int threshold)
      { return bools.Count(b => b) > threshold; }
  }

の使い方は、次になります。

  var bools = new [] {true, true, false, false, false, false, true};
  if (bools.ExceedsThreshold(3))
      // code to execute  ...