Except 拡張メソッドで差集合を取得する
(2017/03/08 17:26:39 created.)
(2017/03/13 8:28:18 modified.)
Except 拡張メソッドは 2 つのシーケンスを比較し、重複した要素を除外します。
Program.cs
namespace Tips_Linq
{
using System;
using System.Linq;
class Program
{
static void Main(string[] args)
{
var numbers1 = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
var numbers2 = new int[] { 3, 4, 5, 6, 7 };
var numbers = numbers1.Except(numbers2);
Console.WriteLine("コレクションの要素は {{ {0} }} です。", string.Join(", ", numbers));
Console.ReadKey();
}
}
}
次のような Person クラスに対して Except 拡張メソッドを使うこともできます。
Person.cs
namespace Tips_Linq
{
using System;
///
/// 人物データを表します。
///
public class Person
{
///
/// 氏名を取得または設定します。
///
public string Name { get; set; }
///
/// 更新日付を取得または設定します。
///
public DateTime Date { get; set; }
}
}
例えば Name プロパティの値が同じものを除外したい場合、Name プロパティで比較するための比較子を用意します。詳細は「Distinct 拡張メソッドで重複する要素をシーケンスから除外する」で説明しているため割愛します。
PersonComparer.cs
namespace Tips_Linq
{
using System.Collections.Generic;
///
/// Person クラスに対する等値比較子を表します。
///
public class PersonComparer : IEqualityComparer<Person>
{
public static readonly PersonComparer DateComparer = new PersonComparer();
///
/// 指定された Person クラスのオブジェクトが等しいかどうかを確認します。
///
/// "x">比較基準を指定します。
/// "y">比較対象を指定します。
///
Date プロパティが等しい場合に true を返します。 public bool Equals(Person x, Person y)
{
return x.Date == y.Date;
}
///
/// ハッシュ値を取得します。
///
/// "obj">ハッシュ値を算出するオブジェクトを指定します。
///
算出したハッシュ値を返します。 public int GetHashCode(Person obj)
{
return obj.Date.GetHashCode();
}
}
}
この比較子を使用することで、Name プロパティ値が同じの要素を除外することができます。
Program.cs
namespace Tips_Linq
{
using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
static void Main(string[] args)
{
Console.WriteLine("== 対象とするシーケンスの内容 =====");
var people1 = GetPeople1();
foreach (var person in people1)
{
Console.WriteLine(person.Name);
}
Console.WriteLine("== 差を取るシーケンスの内容 =====");
var people2 = GetPeople2();
foreach (var person in people2)
{
Console.WriteLine(person.Name);
}
Console.WriteLine("== 差を取った後のシーケンスの内容 =====");
var newPeople = people1.Except(people2, PersonComparer.NameComparer);
foreach (var person in newPeople)
{
Console.WriteLine(person.Name);
}
Console.ReadKey();
}
///
/// 人物コレクションの列挙子を取得します。
///
///
static IEnumerable<Person> GetPeople1()
{
yield return new Person() { Name = "田中 淳平", Date = new DateTime(2011, 5, 2) };
yield return new Person() { Name = "鈴木 ほのか", Date = new DateTime(2014, 3, 24) };
yield return new Person() { Name = "小池 哲司", Date = new DateTime(2002, 6, 13) };
yield return new Person() { Name = "恩田 進", Date = new DateTime(1996, 9, 27) };
yield return new Person() { Name = "中津山 亜希子", Date = new DateTime(2015, 11, 28) };
}
///
/// 人物コレクションの列挙子を取得します。
///
///
static IEnumerable<Person> GetPeople2()
{
yield return new Person() { Name = "田中 淳平", Date = new DateTime(2016, 12, 1) };
yield return new Person() { Name = "小池 哲司", Date = new DateTime(2011, 7, 1) };
}
}
}
Tweet