セット操作 (C#)
LINQ のセット操作は、同一または別個のコレクション (またはセット) に等しい要素があるかどうかに基づいて、結果を生成するクエリ操作です。
次のセクションでは、セット操作を実行する標準クエリ演算子のメソッドの一覧を示します。
メソッド
メソッド名 | 説明 | C# のクエリ式の構文 | 説明を見る |
---|---|---|---|
Distinct または DistinctBy | コレクションから重複する値を削除します。 | 該当なし。 | Enumerable.Distinct Enumerable.DistinctBy Queryable.Distinct Queryable.DistinctBy |
Except または ExceptBy | 差集合 (一方のコレクションにだけ存在し、もう一方のコレクションには出現しない要素) を返します。 | 該当なし。 | Enumerable.Except Enumerable.ExceptBy Queryable.Except Queryable.ExceptBy |
Intersect または IntersectBy | 積集合 (2 つのコレクションのそれぞれに出現する要素) を返します。 | 該当なし。 | Enumerable.Intersect Enumerable.IntersectBy Queryable.Intersect Queryable.IntersectBy |
Union または UnionBy | 和集合 (2 つのコレクションのどちらかに出現する一意の要素) を返します。 | 該当なし。 | Enumerable.Union Enumerable.UnionBy Queryable.Union Queryable.UnionBy |
例
次の例の一部は、太陽系の惑星を表す record
型に依存しています。
namespace SolarSystem;
record Planet(
string Name,
PlanetType Type,
int OrderFromSun)
{
public static readonly Planet Mercury =
new(nameof(Mercury), PlanetType.Rock, 1);
public static readonly Planet Venus =
new(nameof(Venus), PlanetType.Rock, 2);
public static readonly Planet Earth =
new(nameof(Earth), PlanetType.Rock, 3);
public static readonly Planet Mars =
new(nameof(Mars), PlanetType.Rock, 4);
public static readonly Planet Jupiter =
new(nameof(Jupiter), PlanetType.Gas, 5);
public static readonly Planet Saturn =
new(nameof(Saturn), PlanetType.Gas, 6);
public static readonly Planet Uranus =
new(nameof(Uranus), PlanetType.Liquid, 7);
public static readonly Planet Neptune =
new(nameof(Neptune), PlanetType.Liquid, 8);
// Yes, I know... not technically a planet anymore
public static readonly Planet Pluto =
new(nameof(Pluto), PlanetType.Ice, 9);
}
record Planet
は位置指定レコードであり、そのインスタンスを作成するには引数 Name
、Type
、OrderFromSun
が必要です。 Planet
型には、static readonly
の複数の惑星インスタンスがあります。 これらは、よく知られた惑星の便利な定義です。 Type
メンバーは、惑星の種類を示します。
namespace SolarSystem;
enum PlanetType
{
Rock,
Ice,
Gas,
Liquid
};
Distinct
および DistinctBy
次の例は、文字列のシーケンスに対する Enumerable.Distinct メソッドの動作を示しています。 返されたシーケンスには、入力シーケンスからの一意の要素が格納されています。
string[] planets = { "Mercury", "Venus", "Venus", "Earth", "Mars", "Earth" };
IEnumerable<string> query = from planet in planets.Distinct()
select planet;
foreach (var str in query)
{
Console.WriteLine(str);
}
/* This code produces the following output:
*
* Mercury
* Venus
* Earth
* Mars
*/
DistinctBy
は Distinct
に対する別の方法であり、keySelector
を受け取ります。 keySelector
は、ソースの種類の比較識別子として使用されます。 次のような惑星の配列を考えます。
Planet[] planets =
{
Planet.Mercury,
Planet.Venus,
Planet.Earth,
Planet.Mars,
Planet.Jupiter,
Planet.Saturn,
Planet.Uranus,
Planet.Neptune,
Planet.Pluto
};
次のコードでは、惑星が PlanetType
に基づいて判別され、各型の最初の惑星が表示されます。
foreach (Planet planet in planets.DistinctBy(p => p.Type))
{
Console.WriteLine(planet);
}
// This code produces the following output:
// Planet { Name = Mercury, Type = Rock, OrderFromSun = 1 }
// Planet { Name = Jupiter, Type = Gas, OrderFromSun = 5 }
// Planet { Name = Uranus, Type = Liquid, OrderFromSun = 7 }
// Planet { Name = Pluto, Type = Ice, OrderFromSun = 9 }
前述の C# コードでは:
Planet
配列は、固有の惑星の種類ごとに最初の出現にフィルター処理されます。- 結果の
planet
インスタンスが、コンソールに出力されます。
Except
および ExceptBy
次の例で、Enumerable.Except の動作を説明します。 返されたシーケンスには、1 つ目の入力シーケンスのうち、2 つ目の入力シーケンスには存在しない要素が格納されています。
string[] planets1 = { "Mercury", "Venus", "Earth", "Jupiter" };
string[] planets2 = { "Mercury", "Earth", "Mars", "Jupiter" };
IEnumerable<string> query = from planet in planets1.Except(planets2)
select planet;
foreach (var str in query)
{
Console.WriteLine(str);
}
/* This code produces the following output:
*
* Venus
*/
ExceptBy メソッドは Except
に対する別の方法であり、異なる種類と keySelector
の 2 つのシーケンスを受け取ります。 keySelector
は 2 番目のコレクション型と同じ型であり、ソースの種類の比較識別子として使用されます。 次のような惑星の配列を考えます。
Planet[] planets =
{
Planet.Mercury,
Planet.Venus,
Planet.Earth,
Planet.Jupiter
};
Planet[] morePlanets =
{
Planet.Mercury,
Planet.Earth,
Planet.Mars,
Planet.Jupiter
};
最初のコレクションで 2 番目のコレクションに含まれていない惑星を検索するには、second
コレクションとして惑星の名前を射影し、同じ keySelector
を指定することができます。
// A shared "keySelector"
static string PlanetNameSelector(Planet planet) => planet.Name;
foreach (Planet planet in
planets.ExceptBy(
morePlanets.Select(PlanetNameSelector), PlanetNameSelector))
{
Console.WriteLine(planet);
}
// This code produces the following output:
// Planet { Name = Venus, Type = Rock, OrderFromSun = 2 }
前述の C# コードでは:
keySelector
はstatic
ローカル関数として定義されており、惑星の名前で判別します。- 最初の惑星配列は、名前に基づいて、2 番目の惑星配列に存在しない惑星にフィルター処理されます。
- 結果の
planet
インスタンスが、コンソールに出力されます。
Intersect
および IntersectBy
次の例で、Enumerable.Intersect の動作を説明します。 返されたシーケンスには、両方の入力シーケンスに共通する要素が格納されています。
string[] planets1 = { "Mercury", "Venus", "Earth", "Jupiter" };
string[] planets2 = { "Mercury", "Earth", "Mars", "Jupiter" };
IEnumerable<string> query = from planet in planets1.Intersect(planets2)
select planet;
foreach (var str in query)
{
Console.WriteLine(str);
}
/* This code produces the following output:
*
* Mercury
* Earth
* Jupiter
*/
IntersectBy メソッドは Intersect
に対する別の方法であり、異なる種類と keySelector
の 2 つのシーケンスを受け取ります。 keySelector
は、2 番目のコレクションの種類の比較識別子として使用されます。 次のような惑星の配列を考えます。
Planet[] firstFivePlanetsFromTheSun =
{
Planet.Mercury,
Planet.Venus,
Planet.Earth,
Planet.Mars,
Planet.Jupiter
};
Planet[] lastFivePlanetsFromTheSun =
{
Planet.Mars,
Planet.Jupiter,
Planet.Saturn,
Planet.Uranus,
Planet.Neptune
};
惑星の 2 つの配列があり、1 番目は太陽から見て最初の 5 つの惑星を表し、2 番目は太陽から見て最後の 5 つの惑星を表します。 Planet
型は位置指定 record
型であるため、その値の比較セマンティクスを keySelector
の形式で使用できます。
foreach (Planet planet in
firstFivePlanetsFromTheSun.IntersectBy(
lastFivePlanetsFromTheSun, planet => planet))
{
Console.WriteLine(planet);
}
// This code produces the following output:
// Planet { Name = Mars, Type = Rock, OrderFromSun = 4 }
// Planet { Name = Jupiter, Type = Gas, OrderFromSun = 5 }
前述の C# コードでは:
- 2 つの
Planet
配列は、値の比較セマンティクスによって交差されます。 - 結果のシーケンスには、両方の配列で見つかった惑星のみが表示されます。
- 結果の
planet
インスタンスが、コンソールに出力されます。
Union
および UnionBy
次の例は、2 つの文字列シーケンスに対する和集合演算を示しています。 返されたシーケンスには、両方の入力シーケンスからの一意の要素が格納されています。
string[] planets1 = { "Mercury", "Venus", "Earth", "Jupiter" };
string[] planets2 = { "Mercury", "Earth", "Mars", "Jupiter" };
IEnumerable<string> query = from planet in planets1.Union(planets2)
select planet;
foreach (var str in query)
{
Console.WriteLine(str);
}
/* This code produces the following output:
*
* Mercury
* Venus
* Earth
* Jupiter
* Mars
*/
UnionBy メソッドは Union
に対する別の方法であり、同じ種類と keySelector
の 2 つのシーケンスを受け取ります。 keySelector
は、ソースの種類の比較識別子として使用されます。 次のような惑星の配列を考えます。
Planet[] firstFivePlanetsFromTheSun =
{
Planet.Mercury,
Planet.Venus,
Planet.Earth,
Planet.Mars,
Planet.Jupiter
};
Planet[] lastFivePlanetsFromTheSun =
{
Planet.Mars,
Planet.Jupiter,
Planet.Saturn,
Planet.Uranus,
Planet.Neptune
};
これら 2 つのコレクションを 1 つのシーケンスに結合するには、keySelector
を指定します。
foreach (Planet planet in
firstFivePlanetsFromTheSun.UnionBy(
lastFivePlanetsFromTheSun, planet => planet))
{
Console.WriteLine(planet);
}
// This code produces the following output:
// Planet { Name = Mercury, Type = Rock, OrderFromSun = 1 }
// Planet { Name = Venus, Type = Rock, OrderFromSun = 2 }
// Planet { Name = Earth, Type = Rock, OrderFromSun = 3 }
// Planet { Name = Mars, Type = Rock, OrderFromSun = 4 }
// Planet { Name = Jupiter, Type = Gas, OrderFromSun = 5 }
// Planet { Name = Saturn, Type = Gas, OrderFromSun = 6 }
// Planet { Name = Uranus, Type = Liquid, OrderFromSun = 7 }
// Planet { Name = Neptune, Type = Liquid, OrderFromSun = 8 }
前述の C# コードでは:
- 2 つの
Planet
配列は、record
値の比較セマンティクスを使用して結合されます。 - 結果の
planet
インスタンスが、コンソールに出力されます。