[C#] 다른 목록 ID에서 목록 정렬
다음과 같은 식별자가있는 목록이 있습니다.
List<long> docIds = new List<long>() { 6, 1, 4, 7, 2 };
Morover, 다른 <T>
항목 목록 이 있으며 위에서 설명한 ID로 표시됩니다.
List<T> docs = GetDocsFromDb(...)
두 컬렉션 모두에서 동일한 순서를 유지 List<T>
해야하므로 (검색 엔진 점수 이유로 인해) 항목 이 첫 번째 항목 과 동일한 위치 에 있어야합니다. 그리고이 과정은 GetDocsFromDb()
기능 에서 수행 할 수 없습니다 .
필요한 경우 두 번째 목록을 다른 구조 ( Dictionary<long, T>
예 :)로 변경할 수 있지만 변경하지 않는 것이 좋습니다.
LINQ를 사용하여 “일부 ID에 따른 조정”을 수행하는 간단하고 효율적인 방법이 있습니까?
답변
docs = docs.OrderBy(d => docsIds.IndexOf(d.Id)).ToList();
답변
당신은 지정하지 않기 때문에 T
,
IEnumerable<T> OrderBySequence<T, TId>(
this IEnumerable<T> source,
IEnumerable<TId> order,
Func<T, TId> idSelector)
{
var lookup = source.ToDictionary(idSelector, t => t);
foreach (var id in order)
{
yield return lookup[id];
}
}
원하는 것을위한 일반적인 확장입니다.
아마도 이런 식으로 확장을 사용할 수 있습니다.
var orderDocs = docs.OrderBySequence(docIds, doc => doc.Id);
더 안전한 버전은
IEnumerable<T> OrderBySequence<T, TId>(
this IEnumerable<T> source,
IEnumerable<TId> order,
Func<T, TId> idSelector)
{
var lookup = source.ToLookup(idSelector, t => t);
foreach (var id in order)
{
foreach (var t in lookup[id])
{
yield return t;
}
}
}
source
와 정확히 압축되지 않으면 작동합니다 order
.
답변
Jodrell의 답변이 가장 좋지만 실제로 그는 다시 구현했습니다 System.Linq.Enumerable.Join
. Join은 또한 Lookup을 사용하고 소스 순서를 유지합니다.
docIds.Join(
docs,
i => i,
d => d.Id,
(i, d) => d);
답변
간단한 접근 방법 중 하나는 주문 순서로 압축하는 것입니다.
List<T> docs = GetDocsFromDb(...).Zip(docIds, Tuple.Create)
.OrderBy(x => x.Item2).Select(x => x.Item1).ToList();