질문:
공통 키 필드를 기반으로 두 객체 목록간에 완전히 연결되는 방법으로, 다른 목록에 해당 일치가 없더라도 두 목록의 모든 레코드가 결과에 포함되도록하는 방법은 무엇입니까?
답변:
LINQ에서 전체 외부 연결을 구현하려면 다음과 같이 사용자 정의 확장 메소드를 정의 할 수 있습니다.
public static IEnumerable FullOuterJoin(
this IEnumerable a,
IEnumerable b,
Func selectKeyA,
Func selectKeyB,
Func projection,
TA defaultA = default(TA),
TB defaultB = default(TB),
IEqualityComparer cmp = null)
{
cmp = cmp ?? EqualityComparer.Default;
var alookup = a.ToLookup(selectKeyA, cmp);
var blookup = b.ToLookup(selectKeyB, cmp);
var keys = new HashSet(alookup.Select(p => p.Key), cmp);
keys.UnionWith(blookup.Select(p => p.Key));
var join = from key in keys
from xa in alookup[key].DefaultIfEmpty(defaultA)
from xb in blookup[key].DefaultIfEmpty(defaultB)
select projection(xa, xb, key);
return join;
}
제공된 예제에는 firstNames
및 lastNames
가 있습니다. 전체 외부 연결을 수행하려면 다음 코드를 사용할 수 있습니다.
var outerJoin = from first in firstNames
join last in lastNames
on first.ID equals last.ID
into temp
from last in temp.DefaultIfEmpty()
select new
{
id = first != null ? first.ID : last.ID,
firstname = first != null ? first.Name : string.Empty,
surname = last != null ? last.Name : string.Empty
};
firstNames 의 각 레코드는
lastNames 의 첫 번째 일치 레코드에 연결되며 일치하지 않으면 기본값에 연결됩니다.
는 temp 문으로
lastNames 에서 일치하는 레코드의 임시 컬렉션을 생성하여
defaultifempty () 를 적용하여 불일치 레코드가 포함되도록합니다. 이것은 실제로 전체 의미에서 전체 외부 연결이 아니라 왼쪽 외부 연결을 구현합니다. 전체 외부 연결을 달성하려면
fullouterjoin 확장 메소드를 사용하여 위에서 사용자 정의해야합니다.
Id FirstName LastName --------------------- 1 John Doe 2 Sue 3 Smith
ID FirstName LastName
-- --------- --------
1 John Doe
2 Sue
3 Smith
는 일치하지 않는 레코드의 기본값을 지정할 수있는 확장 방법을 제공합니다. 이 예에서는 불일치 한 이름과 불일치 ID에 대한 음의 정수에 대해
6. 성능 고려 사항
7.
이 완전히 외부 연결 구현은 현재 LINQ 표준의 일부가 아니지만 향후 버전에 포함하는 것이 좋습니다. 표준 LINQ는 전체 외부 연결을 직접 지원하지 않으며이를 구현하려면 사용자 정의 확장 방법이 필요합니다.
부인 성명: 제공된 모든 리소스는 부분적으로 인터넷에서 가져온 것입니다. 귀하의 저작권이나 기타 권리 및 이익이 침해된 경우 자세한 이유를 설명하고 저작권 또는 권리 및 이익에 대한 증거를 제공한 후 이메일([email protected])로 보내주십시오. 최대한 빨리 처리해 드리겠습니다.
Copyright© 2022 湘ICP备2022001581号-3