web-dev-qa-db-ja.com

別のリストIDからリストを並べ替える

私はこのようないくつかの識別子を持つリストを持っています:

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

モーバー、<T>アイテムの別のリストがあります。これらのリストは、上記のIDで表されます。

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

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

必要に応じて、2番目のリストを他の構造(Dictionary<long, T>など)に変更することもできますが、変更しないことをお勧めします。

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

111
Borja López
docs = docs.OrderBy(d => docsIds.IndexOf(d.Id)).ToList();
270
Denys Denysenko

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と正確にZipしない場合に機能します。

14
Jodrell
docIds.Join(
  docs,
  i => i,
  d => d.Id,
  (i, d) => d)
0
Kladzey