いろいろ備忘録日記

主に .NET とか Go とか Flutter とか Python絡みのメモを公開しています。

Linq入門記-31 (LINQ To Object, Distinct)


今回は、Distinct拡張メソッドについてです。


Distinct拡張メソッドは、SQLでのDISTINCTと同じです。重複するデータを除いてくれます。
重複するデータを除くという処理は、実務ではよくお目にかかる処理です。
今までは、ループして重複するデータを除いたりしていましたが、Distinct拡張メソッドを利用すれば一発で処理できます。


Distinct拡張メソッドの書式は以下の通りです。

public static IEnumerable<TSource> Distinct<TSource>(
	this IEnumerable<TSource> source
)

public static IEnumerable<TSource> Distinct<TSource>(
	this IEnumerable<TSource> source,
	IEqualityComparer<TSource> comparer
)


一つ目の書式が一番よく利用される形のものですね。
2つめの書式は、一つ目の分にIEqualityComparer comparerが追加されています。
キーの同値性を独自の方法で決定する際に利用します。


以下、サンプルです。
以下のサンプルでは、基本型のシーケンスに対してのDistinctと、カスタムデータのシーケンスに対してのDistinctの
両方を実行してみています。

    #region LinqSamples-28
    public class LinqSamples28 : 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()
        {
            //
            // 引数なしのDistinct拡張メソッドを利用.
            // この場合、既定のIEqualityComparer<T>を用いて比較が行われる。
            // 
            var numbers = new int[]
                          {
                            1, 2, 3, 4, 5,
                            1, 2, 3, 6, 7
                          };
                          
            Console.WriteLine(JoinElements(numbers.Distinct()));
            
            //
            // 引数にIEqualityComparer<T>を指定して、Distinct拡張メソッドを利用。
            // この場合、引数に指定したComparerを用いて比較が行われる。
            //
            var people  = new Person[]
                          { 
                                new Person { Name = "gsf_zero1" }, 
                                new Person { Name = "gsf_zero2" }, 
                                new Person { Name = "gsf_zero1" },
                                new Person { Name = "gsf_zero3" }
                          };
                          
            Console.WriteLine(JoinElements(people.Distinct(new PersonComparer())));
        }
        
        string JoinElements<T>(IEnumerable<T> elements)
        {
            return string.Join(",", elements.Select(item => item.ToString()));
        }
    }
    #endregion


実行結果は以下の通りです。

  1,2,3,4,5,6,7
  [NAME = gsf_zero1],[NAME = gsf_zero2],[NAME = gsf_zero3]

================================
過去の記事については、以下のページからご参照下さい。