从其他列表ID中排序列表

时间:2013-03-07 15:36:36

标签: c# linq sorting collections

我有一个包含这样的标识符的列表:

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”的“ordenation”?

4 个答案:

答案 0 :(得分:258)

docs = docs.OrderBy(d => docsIds.IndexOf(d.Id)).ToList();

答案 1 :(得分:13)

由于您未指定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;
        }
    }
}

如果sourceorder完全没有拉链,则会有效。

答案 2 :(得分:0)

docIds.Join(
  docs,
  i => i,
  d => d.Id,
  (i, d) => d)

答案 3 :(得分:-3)

一种简单的方法是使用排序顺序进行压缩:

List<T> docs = GetDocsFromDb(...).Zip(docIds, Tuple.Create)
               .OrderBy(x => x.Item2).Select(x => x.Item1).ToList();
相关问题