设置操作 (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 | 返回交集,交集指同时出现在两个集合中的元素。 | 不适用。 | Enumerable.Intersect Enumerable.IntersectBy Queryable.Intersect Queryable.IntersectBy |
Union 或 UnionBy | 返回并集,并集指位于两个集合中任一集合的唯一的元素。 | 不适用。 | 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 的行为。 返回的序列只包含位于第一个输入序列但不位于第二个输入序列的元素。
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
。 keySelector
与第二个集合的类型相同,用作源类型的比较鉴别器。 请考虑以下行星阵列:
Planet[] planets =
{
Planet.Mercury,
Planet.Venus,
Planet.Earth,
Planet.Jupiter
};
Planet[] morePlanets =
{
Planet.Mercury,
Planet.Earth,
Planet.Mars,
Planet.Jupiter
};
若要在第一个集合中查找不在第二个集合中的行星,可以将行星名称投影为 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
局部函数,用于区分行星名称。- 第一个行星阵列会根据名称筛选为第二个行星阵列中未找到的行星。
- 将生成的
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
。 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
};
有两个行星阵列;一个代表来自太阳系的第五个行星,第二个代表来自太阳系的最后五个行星。 由于 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# 代码中:
- 这两个
Planet
阵列通过它们的值比较语义相交。 - 只有在这两个阵列中都找到的行星才会出现在结果序列中。
- 将生成的
planet
实例写入控制台。
Union
和 UnionBy
以下示例演示对两个字符串序列执行的联合操作。 返回的序列包含两个输入序列的唯一元素。
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
。 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
};
若要将这两个集合联合到一个序列中,请提供 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# 代码中:
- 这两个
Planet
阵列使用它们的record
值比较语义交织在一起。 - 将生成的
planet
实例写入控制台。