C# 从另一个列表 ID 对列表进行排序

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15275269/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 16:13:59  来源:igfitidea点击:

Sort a list from another list IDs

c#linqsortingcollections

提问by Borja López

I have a list with some identifiers like this:

我有一个包含一些标识符的列表,如下所示:

List<long> docIds = new List<long>() { 6, 1, 4, 7, 2 };

Morover, I have another list of <T>items, which are represented by the ids described above.

此外,我还有另一个<T>项目列表,它们由上述 id 表示。

List<T> docs = GetDocsFromDb(...)

I need to keep the same order in both collections, so that the items in List<T>must be in the same position than in the first one (due to search engine scoring reasons). And this process cannot be done in the GetDocsFromDb()function.

我需要在两个集合中保持相同的顺序,以便项目中的项目List<T>必须与第一个项目位于相同的位置(由于搜索引擎评分的原因)。而这个过程是无法在GetDocsFromDb()函数中完成的。

If necessary, it's possible to change the second list into some other structure (Dictionary<long, T>for example), but I'd prefer not to change it.

如有必要,可以将第二个列表更改为其他结构(Dictionary<long, T>例如),但我不想更改它。

Is there any simple and efficient way to do this "ordenation depending on some IDs" with LINQ?

是否有任何简单有效的方法可以使用 LINQ 执行此“根据某些 ID 进行排序”?

采纳答案by Denys Denysenko

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

回答by Albin Sunnanbo

One simple approach is to zip with the ordering sequence:

一种简单的方法是按顺序压缩:

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

回答by Jodrell

Since you don't specify T,

既然你没有指定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];
    }
}

Is a generic extension for what you want.

是您想要的通用扩展。

You could use the extension like this perhaps,

也许你可以像这样使用扩展名,

var orderDocs = docs.OrderBySequence(docIds, doc => doc.Id);


A safer version might be

更安全的版本可能是

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;
        }
    }
}

which will work if sourcedoes not zip exactly with order.

如果source不与 .zip 完全压缩,这将起作用order

回答by Kladzey

Jodrell's answer is best, but actually he reimplemented System.Linq.Enumerable.Join. Join also uses Lookup and keeps ordering of source.

Jodrell 的回答是最好的,但实际上他重新实现了System.Linq.Enumerable.Join. Join 也使用 Lookup 并保持源的顺序。

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