집합 작업(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 메서드는 이종 형식의 두 시퀀스와 keySelector
를 사용하는 Except
에 대한 대체 접근 방식입니다. 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 메서드는 이종 형식의 두 시퀀스와 keySelector
를 사용하는 Intersect
에 대한 대체 접근 방식입니다. 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 메서드는 동일한 형식의 두 시퀀스와 keySelector
를 사용하는 Union
에 대한 대체 접근 방식입니다. 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
인스턴스는 콘솔에 기록됩니다.