web-dev-qa-db-fra.com

Trier une liste d'une autre liste

J'ai une liste avec des identifiants comme celui-ci:

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

De plus, j'ai une autre liste d'éléments <T>, Représentés par les identifiants décrits ci-dessus.

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

Je dois conserver le même ordre dans les deux collections, afin que les éléments de List<T> Soient dans la même position que dans le premier (pour des raisons de notation dans les moteurs de recherche). Et ce processus ne peut pas être effectué dans la fonction GetDocsFromDb().

Si nécessaire, il est possible de changer la deuxième liste en une autre structure (Dictionary<long, T> Par exemple), mais je préférerais ne pas la changer.

Existe-t-il un moyen simple et efficace de faire cette "ordination en fonction de certains identifiants" avec LINQ?

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

Puisque vous ne spécifiez pas 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];
    }
}

Est une extension générique pour ce que vous voulez.

Vous pourriez utiliser l'extension comme ceci peut-être,

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

Une version plus sûre pourrait être

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

ce qui fonctionnera si source ne zip pas exactement avec order.

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