今回は、Union拡張メソッドとConcat拡張メソッドについてです。
Union拡張メソッドは、SQLでのUNIONと同じです。2つのシーケンスを結合して、且つ、重複を除外します。
SQLでのUNION ALLを行うには、Concat拡張メソッドを利用します。Concat拡張メソッドは、重複を含めて
2つのシーケンスをそのまま結合します。
なので、ConcatしてDistinctすると、Unionしたことと同じになります。
Union拡張メソッドの書式は以下の通りです。
public static IEnumerable<TSource> Union<TSource>( this IEnumerable<TSource> first, IEnumerable<TSource> second ) public static IEnumerable<TSource> Union<TSource>( this IEnumerable<TSource> first, IEnumerable<TSource> second, IEqualityComparer<TSource> comparer )
一つ目の書式が一番よく利用される形のものですね。
2つめの書式は、一つ目の分にIEqualityComparer
キーの同値性を独自の方法で決定する際に利用します。
Concat拡張メソッドの書式は以下の通りです。
public static IEnumerable<TSource> Concat<TSource>( this IEnumerable<TSource> first, IEnumerable<TSource> second )
Concatの場合、単純に2つのシーケンスを結合するだけなので
IEqualityComparer
以下、サンプルです。
以下のサンプルでは、基本型のシーケンスに対してのUnion, Concatと、カスタムデータのシーケンスに対してのUnion, Concatの
両方を実行してみています。
#region LinqSamples-29 public class LinqSamples29 : IExecutable { class Person { public string Name { get; set; } public override string ToString() { return string.Format("[NAME = {0}]", Name); } } class PersonComparer : EqualityComparer<Person> { public override bool Equals(Person p1, Person p2) { if (Object.Equals(p1, p2)) { return true; } if (p1 == null || p2 == null) { return false; } return (p1.Name == p2.Name); } public override int GetHashCode(Person p) { return p.Name.GetHashCode(); } } public void Execute() { // // 引数なしのUnion拡張メソッドを利用. // この場合、既定のIEqualityComparer<T>を用いて比較が行われる。 // // Union拡張メソッドは、SQLでいうUNIONと同じ。(重複を除外する) // SQLでいう、UNION ALL(重複をそのまま残す)を行うにはConcat拡張メソッドを利用する。 // ConcatしてDistinctするとUnionと同じ事になる。 // var numbers1 = new int[] { 1, 2, 3, 4, 5 }; var numbers2 = new int[] { 1, 2, 3, 6, 7 }; Console.WriteLine("UNION = {0}", JoinElements(numbers1.Union(numbers2))); Console.WriteLine("CONCAT = {0}", JoinElements(numbers1.Concat(numbers2))); Console.WriteLine("CONCAT->DISTINCT = {0}", JoinElements(numbers1.Concat(numbers2).Distinct())); // // 引数にIEqualityComparer<T>を指定して、Union拡張メソッドを利用。 // この場合、引数に指定したComparerを用いて比較が行われる。 // var people1 = new Person[] { new Person { Name = "gsf_zero1" }, new Person { Name = "gsf_zero2" }, new Person { Name = "gsf_zero1" }, new Person { Name = "gsf_zero3" } }; var people2 = new Person[] { new Person { Name = "gsf_zero4" }, new Person { Name = "gsf_zero5" }, new Person { Name = "gsf_zero6" }, new Person { Name = "gsf_zero1" } }; Console.WriteLine("UNION = {0}", JoinElements(people1.Union(people2, new PersonComparer()))); Console.WriteLine("CONCAT = {0}", JoinElements(people1.Concat(people2))); Console.WriteLine("CONCAT->DISTINCT = {0}", JoinElements(people1.Concat(people2).Distinct(new PersonComparer()))); } string JoinElements<T>(IEnumerable<T> elements) { return string.Join(",", elements.Select(item => item.ToString())); } } #endregion
実行結果は以下の通りです。
UNION = 1,2,3,4,5,6,7 CONCAT = 1,2,3,4,5,1,2,3,6,7 CONCAT->DISTINCT = 1,2,3,4,5,6,7 UNION = [NAME = gsf_zero1],[NAME = gsf_zero2],[NAME = gsf_zero3],[NAME = gsf_zero4],[NAME = gsf_zero5],[NAME = gsf_zero6] CONCAT = [NAME = gsf_zero1],[NAME = gsf_zero2],[NAME = gsf_zero1],[NAME = gsf_zero3],[NAME = gsf_zero4],[NAME = gsf_zero5],[NAME = gsf_zero6],[NAME = gsf_zero1] CONCAT->DISTINCT = [NAME = gsf_zero1],[NAME = gsf_zero2],[NAME = gsf_zero3],[NAME = gsf_zero4],[NAME = gsf_zero5],[NAME = gsf_zero6]
================================
過去の記事については、以下のページからご参照下さい。
- いろいろ備忘録日記まとめ