0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

LINQで選択肢の全組み合わせ展開(クエリ式を使う)

Last updated at Posted at 2017-12-07

LINQで選択肢の全組み合わせ展開の続き。
選択肢数が可変でもOK!とするために再帰でやったけど、
選択肢数も型も決まってるんなら、こっちの方がスマートかと。

というわけで実装。

クエリ式で実装

SQLで全組み合わせ作る時に、結合条件なしで直積を作ってたよね、ってことで、
クエリ式でもjoinを使わずに、選択肢の数だけ**「from~in~」**を並べて全組み合わせを展開。
その後で、重複が無いものだけを引っこ抜く。

Program.cs
        public static void Main(string[] args)
        {
            var items = new int[] { 1, 2, 3 };

            //結合条件なしで重複ありの全組み合わせを展開
            //展開結果は配列にする
            //q1{1,1,1}{1,1,2}{1,1,3}{1,2,1}…{3,3,3}
            var q1 = from s1 in items
                     from s2 in items
                     from s3 in items
                     select new int[] { s1, s2, s3 };

            //各要素の重複なしのレコードのみ抽出して返す
            //要素の個数と、各要素の値の種類数が一致していれば重複無しと判断
            // q1={1,3,1}の場合、要素の個数は3、値の種類数は2(1と3しかないから)→×:除外
            // q1={1,3,2}の場合、要素の個数は3、値の種類数は3→○:抽出
            // q1={1,1,1}の場合、要素の個数は3、値の種類数は1(1しかないから)→×:除外
            var q2 = q1.Where(ar => ar.Length == ar.Distinct().Count());

            q2.DisplayElement<int>();
        }

実行結果確認用のコード

結果確認用の拡張メソッド。(前回作ったそのままでよかったね。。。)

Extention.cs
        /// <summary>
        /// 結果表示用
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="query"></param>
        public static void DisplayElement<T>(this IEnumerable<T[]> query)
        {
            foreach (var q in query)
            {
                Console.WriteLine(string.Join(" ", q));
            }
        }

実行結果

image.png

おっけー!

修正前

albireoさんからアドバイスをいただき、修正しました。修正前は↓。
Selectの射影を匿名型で取る意味ってなかったね。。。

修正前のコード

【修正前】Program.cs
        public static void Main(string[] args)
        {
            var items = new int[] { 1, 2, 3 };

            //結合条件なしで重複ありの全組み合わせを展開
            //q1{1,1,1}{1,1,2}{1,1,3}{1,2,1}…{3,3,3}
            var q1 = from s1 in items
                     from s2 in items
                     from s3 in items
                     select new { N1 = s1, N2 = s2, N3 = s3 };

            //各要素の重複なしのレコードのみ抽出して返す
            //要素の個数と、各要素の値の種類数が一致していれば重複無しと判断
            // q1={1,3,1}の場合、要素の個数は3、値の種類数は2(1と3しかないから)→×:除外
            // q1={1,3,2}の場合、要素の個数は3、値の種類数は3→○:抽出
            // q1={1,1,1}の場合、要素の個数は3、値の種類数は1(1)→×:除外
            var q2 = q1.Where(v =>
            {
                var ar = new int[] { v.N1, v.N2, v.N3 };
                return ar.Length == ar.Distinct().Count();
            }
            );
            q2.DisplayElement();
        }

修正前の実行結果

image.png

0
1
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?