ド・モルガンの法則による手抜き動的クエリ

ほっぽで動的クエリが必要になり探してたら結構めんどくさいなーと思ったので、なんとか手抜きできそうな方法を考えたらふと思いついたのでメモ。

動的クエリ(Where限定)でも全AND検索の場合はすぐできます。例えば条件A1, A2,…とあったとして

foreach(…)
{
条件Aiが満たされるか
  →満たされない : falseを返す
}
trueを返す

とすればいいだけです。

ところがOR検索の場合、このようにループで回すことができません。そこで手抜きする場合は全AND検索に置き換える方法を考えます。全OR検索の場合に限り、論理式変形で全AND検索に変更することができます。
A \vee B \ \vee C \dots = \neg(\neg A \wedge \neg B \wedge \neg C \dots)
ドモルガンの法則を適用しただけです。ちゃんと全AND検索になってますね。

(例)2の倍数または3の倍数または5の倍数を列挙する
与えられた数字から2,3,5の倍数を列挙してみます。もちろんこの倍数は何でもOKです。

static void Main()
{
var data = Enumerable.Range(0, 20);//とりあえず0~19まで

int[] factor = new int[] { 2, 3, 5 };

//dataからfactorの倍数をOR検索で抜き出す
var query = from x in data
where isMultiple(x, factor)
select x;
Console.WriteLine(string.Join(", ", query));
}

static bool isMultiple(int x, int[] factor)
{
foreach (int i in factor)
{
bool flag = x % i == 0;//条件A
if (flag) return flag;//条件¬Aが満たされないならば、(!false = )trueを返す
}
return false;//falseを返す
}


結果はそのままの通り、

//出力 : 0, 2, 3, 4, 5, 6, 8, 9, 10, 12, 14, 15, 16, 18


AND検索との違いをまとめると、
 AND検索 :
  ループの途中で抜ける文→if(判定 == false) return false;
  末尾の返り値→return true;
 OR検索(をAND検索に変換したもの) : 
  ループの途中で抜ける文→if(判定 == true) return true;
  末尾の返り値→return false;

結果的にはANDのまるまる逆になるみたいですね。知らない人がパッと見たときの可読性はアレかもしれないw あとANDとORが混じってたときやwhere以外を分離できないときははどうしようもないので、ライブラリやら式木でちゃんと実装しましょう。

書いてみて思った。これすごく当たり前で書くまでもなかった。
スポンサーサイト
プロフィール

こしあん

Author:こしあん
(:3[____]
【TwitterID : koshian2】
【ほしい物リスト】http://goo.gl/bDtvG2

Twitter
カウンター
天気予報

-天気予報コム- -FC2-
カテゴリ
月別アーカイブ
最新記事
最新トラックバック
検索フォーム
リンク