194

次のような識別子を含むリストがあります。

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

<T>さらに、上記の ID で表されるアイテムの別のリストがあります。

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

両方のコレクションで同じ順序を維持する必要があるためList<T>、最初のコレクションと同じ位置にある必要があります (検索エンジンのスコアリングの理由により)。そして、このプロセスは関数では実行できませんGetDocsFromDb()

必要に応じて、2 番目のリストを別の構造 (Dictionary<long, T>たとえば) に変更することもできますが、私はそれを変更したくありません。

この「いくつかのIDに応じた順序付け」をLINQで行う簡単で効率的な方法はありますか?

4

4 に答える 4

411
docs = docs.OrderBy(d => docsIds.IndexOf(d.Id)).ToList();
于 2013-03-07T15:42:22.663 に答える
33

指定しないので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ます。

于 2013-03-07T15:53:30.433 に答える
-4

簡単な方法の 1 つは、次の順序で圧縮することです。

List<T> docs = GetDocsFromDb(...).Zip(docIds, Tuple.Create)
               .OrderBy(x => x.Item2).Select(x => x.Item1).ToList();
于 2013-03-07T15:44:00.897 に答える