はじめに
前回(【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で取得した結果は元のデータとは別の領域に保存されている思うのですが、大量データを処理する場合に領域不足が起きないのか気になりました。
機会が有ればそのあたりも調べてみたいと思います。