Bor*_*pez 118 c# linq sorting collections
我有一个包含这样的标识符的列表:
List<long> docIds = new List<long>() { 6, 1, 4, 7, 2 };
Run Code Online (Sandbox Code Playgroud)
Morover,我有另一个<T>项目列表,由上述id表示.
List<T> docs = GetDocsFromDb(...)
Run Code Online (Sandbox Code Playgroud)
我需要在两个集合中保持相同的顺序,以便项目List<T>必须与第一个中的位置相同(由于搜索引擎评分原因).而且这个过程不能在GetDocsFromDb()函数中完成.
如有必要,可以将第二个列表更改为其他结构(Dictionary<long, T>例如),但我不想更改它.
是否有任何简单有效的方法来使用LINQ进行"取决于某些ID"的"ordenation"?
Den*_*nko 283
docs = docs.OrderBy(d => docsIds.IndexOf(d.Id)).ToList();
Run Code Online (Sandbox Code Playgroud)
Jod*_*ell 17
既然你没有指定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];
}
}
Run Code Online (Sandbox Code Playgroud)
是您想要的通用扩展.
您也许可以使用这样的扩展名,
var orderDocs = docs.OrderBySequence(docIds, doc => doc.Id);
Run Code Online (Sandbox Code Playgroud)
更安全的版本可能是
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;
}
}
}
Run Code Online (Sandbox Code Playgroud)
如果source不完全拉链,它将工作order.
Kla*_*zey 10
Jodrell 的回答是最好的,但实际上他重新实现了System.Linq.Enumerable.Join. Join 也使用 Lookup 并保持源的顺序。
docIds.Join(
docs,
i => i,
d => d.Id,
(i, d) => d);
Run Code Online (Sandbox Code Playgroud)