4
3

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 3 years have passed since last update.

【C#】DataTable でのLINQの使い方(3)

Posted at

はじめに

前回(【C#】DataTable でのLINQの使い方(2))に引き続き、C#のDataTableクラスでLINQを使ったコードを簡単にまとめた内容を記載します。

重複行の削除

DataTable で重複している行を削除
※重複行を削除は使う場合は少ないかと、DBから取得する場合は重複行を削除しているかと思うので。

        DataTable member = new DataTable();
        member.Columns.Add("No", typeof(int));
        member.Columns.Add("Name", typeof(string));
        member.Columns.Add("Age", typeof(int));
        member.Columns.Add("Address", typeof(string));

        member.Rows.Add(1, "太郎", 10, "東京");
        member.Rows.Add(3, "三郎", 30, "大阪");
        member.Rows.Add(1, "太郎", 10, "東京");     // 差異無
        member.Rows.Add(1, "四郎", 10, "東京");     // 差異有
        member.Rows.Add(2, "次郎", 20, "名古屋");

        // 重複行を削除
        DataRow[] rows =
            member.AsEnumerable()
                  .Distinct(DataRowComparer.Default)
                  .ToArray();

        Console.WriteLine("重複する行を削除した結果");
        foreach (DataRow row in rows)
            Console.WriteLine("No:{0},Name:{1},Age:{2},Address:{3}"
                    , row["No"], row["Name"], row["Age"], row["Address"]);

        // 指定項目の重複行を削除
        DataRow[] rows2 =
            member.AsEnumerable()
                  .GroupBy(x => x.Field<int>("No"))
                  .Select(y => y.First())
                  .ToArray();

        Console.WriteLine("指定項目の重複行を削除した結果");
        foreach (DataRow row in rows2)
            Console.WriteLine("No:{0},Name:{1},Age:{2},Address:{3}"
                    , row["No"], row["Name"], row["Age"], row["Address"]);

簡単な説明

  • 全項目の値が重複している行を削除する場合は「Distinct」を利用する事で削除されます。
    ※サンプルでは「差異無」の行のみが削除されています。

  • 項目別で値が重複している行を削除する場合は「GroupBy」を利用する事で削除されます。
    また、削除される行は2行目以降になります。
    ※サンプルでは「No」が重複している「差異無」「差異有」の行が削除されています。

出力結果

重複する行を削除した結果
No:1,Name:太郎,Age:10,Address:東京
No:3,Name:三郎,Age:30,Address:大阪
No:1,Name:四郎,Age:10,Address:東京
No:2,Name:次郎,Age:20,Address:名古屋

指定項目の重複行を削除した結果
No:1,Name:太郎,Age:10,Address:東京
No:3,Name:三郎,Age:30,Address:大阪
No:2,Name:次郎,Age:20,Address:名古屋

複数テーブルでの重複行又は重複行以外の取得

2つのテーブルで重複していない行の取得、又は重複している行の取得

        DataTable member = new DataTable();
        member.Columns.Add("No", typeof(int));
        member.Columns.Add("Name", typeof(string));
        member.Columns.Add("Age", typeof(int));
        member.Columns.Add("Address", typeof(string));

        member.Rows.Add(1, "太郎", 10, "東京");
        member.Rows.Add(1, "四郎", 10, "東京");     // 差異有
        member.Rows.Add(2, "次郎", 20, "名古屋");
        member.Rows.Add(3, "三郎", 30, "大阪");

        DataTable member2 = new DataTable();
        member2 = member.Clone();

        member2.Rows.Add(1, "太郎", 10, "東京");
        member2.Rows.Add(2, "次郎", 20, "名古屋");
        member2.Rows.Add(3, "五郎", 30, "大阪");     // 差異有

        // 「member」テーブルのみに存在する行を取得
        DataRow[] rows =
            member.AsEnumerable()
                  .Except(member2.AsEnumerable(), DataRowComparer.Default)
                  .ToArray();

        Console.WriteLine("「member」テーブルのみに存在する行を取得した結果");
        foreach (DataRow row in rows)
            Console.WriteLine("No:{0},Name:{1},Age:{2},Address:{3}"
                    , row["No"], row["Name"], row["Age"], row["Address"]);

        // 「member」「member2」テーブル両方に存在する行を取得
        DataRow[] rows2 =
            member.AsEnumerable()
              .Intersect(member2.AsEnumerable(), DataRowComparer.Default)
              .ToArray();

        Console.WriteLine("両テーブルに存在する行を取得した結果");
        foreach (DataRow row in rows2)
            Console.WriteLine("No:{0},Name:{1},Age:{2},Address:{3}"
                    , row["No"], row["Name"], row["Age"], row["Address"]);

簡単な説明

  • 重複していない行を取得する場合は「Except」を利用する事で取得できます。
    サンプルでは、「member」テーブルで「member2」テーブルのレコードと重複していない行を取得しています。

  • 重複している行を取得する場合は「Intersect」を利用する事で取得できます。
    サンプルでは、「member」テーブルと「member2」テーブルのレコードと重複している行を取得しています。

  • 今回の方法では項目別の重複には対象できません。

    やり方については別項目で書くと思います。

出力結果

「member」テーブルのみに存在する行を取得した結果
No:1,Name:四郎,Age:10,Address:東京
No:3,Name:三郎,Age:30,Address:大阪

両テーブルに存在する行を取得した結果
No:1,Name:太郎,Age:10,Address:東京
No:2,Name:次郎,Age:20,Address:名古屋

おわりに

前回に続きLINQについて書いてみました。
記事を書いている時に思ったのですが、LINQで取得した結果は元のデータとは別の領域に保存されている思うのですが、大量データを処理する場合に領域不足が起きないのか気になりました。
機会が有ればそのあたりも調べてみたいと思います。

4
3
0

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
4
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?