从其他列表id排序列表
本文关键字:列表 排序 id 其他 | 更新日期: 2023-09-27 18:02:41
我有一个像这样的一些标识符列表:
List<long> docIds = new List<long>() { 6, 1, 4, 7, 2 };
此外,我还有另一个<T>
项列表,它由上面描述的id表示。
List<T> docs = GetDocsFromDb(...)
我需要在两个集合中保持相同的顺序,以便List<T>
中的项目必须位于与第一个相同的位置(由于搜索引擎评分原因)。而这个过程在GetDocsFromDb()
函数中是无法完成的。
如果有必要,可以将第二个列表更改为其他结构(例如Dictionary<long, T>
),但我宁愿不更改它。
是否有任何简单有效的方法来做这个"顺序取决于一些id"与LINQ?
docs = docs.OrderBy(d => docsIds.IndexOf(d.Id)).ToList();
由于没有指定T
,
public static 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);
更安全的版本可能是
public static 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();