テスト問題やってる時にでてきたので。勉強ついでに~
例えば、{a,b,c}のn=3であれば、
{}
{a}
{b}
{c}
{a,b}
{a,c}
{b,c}
{a,b,c}
の8種類を出力したい。
ということで以下のように作成しました。
n個のコレクションから0~n個取り出すすべてのパターンを列挙
IEnumerableクラスを拡張して作成します。
Collect.cs
public static class IEnumerable
{
public static IEnumerable<IEnumerable<T>> MultiSelect<T>(this IEnumerable<T> items)
{
var cnt = items.Count();
for (var i = 0; i < Math.Pow(2, cnt); i++)
{
var s = Convert.ToString(i, 2).PadLeft(cnt, '0').Reverse().ToList();
var sOn = items.Where((_, index) => s[index].ToString() == "1");
yield return sOn;
}
}
}
0~2^nまでの2進数の文字列を取得すると、
"…0000","…0001","…0010",~(中略)~"…1111"と入っているはずなので、
**"1"が入っている桁=取り出す、"0"が入っている桁=取り出さない **
と判断するだけ。
nullを表示したくなければi=1から始めること。
順番が逆で良いなら.Reverse().ToList()は不要。
使い方は簡単。
Main.cs
static void Main(string[] args)
{
var i = new int[]{ 1, 2, 3 };
var iRet = i.MultiSelect().ToList();
}
結果は以下のようになります。
1
2
12
3
13
23
123
追記
よし出来た!と思ったんだけど、作ってから気づいた。
コンビネーション処理をどこかから拾ってきて
nC0+nC1+…nCn(=2^n個) で計算したほうが楽だった……