Sortuj listę z innego identyfikatora listy

Mam listę z takimi identyfikatorami:

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

Co więcej, mam jeszcze jedną listę <T> elementów, które są reprezentowane przez identyfikatory opisane powyżej.

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

Muszę zachować tę samą kolejność w obu kolekcjach, aby pozycje w List<T> musiały znajdować się w tej samej pozycji, co w pierwszej (ze względu na punktację wyszukiwarek). I tego procesu nie można wykonać w funkcji GetDocsFromDb().

W razie potrzeby można zmienić drugą listę na inną struktura (Dictionary<long, T> na przykład), ale wolałbym tego nie zmieniać.

Czy Jest jakiś prosty i skuteczny sposób, aby zrobić to "ordenation w zależności od niektórych IDs" z LINQ?

Author: Ry-, 2013-03-07

3 answers

docs = docs.OrderBy(d => docsIds.IndexOf(d.Id)).ToList();
 206
Author: Denys Denysenko,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-03-07 15:42:22

Ponieważ nie podajesz 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];
    }
}

Jest ogólnym rozszerzeniem tego, co chcesz.

Możesz użyć rozszerzenia w ten sposób być może,

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

Bezpieczniejszą wersją może być

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

Które będzie działać, jeśli source nie zapina się dokładnie za pomocą order.

 7
Author: Jodrell,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-03-07 16:00:37

Jednym prostym podejściem jest zip z sekwencją porządkową:

List<T> docs = GetDocsFromDb(...).Zip(docIds, Tuple.Create)
               .OrderBy(x => x.Item2).Select(x => x.Item1).ToList();
 -2
Author: Albin Sunnanbo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-03-07 15:44:00