Sort a list from another list id

I have a list with some identifiers like this:

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

Morover, I have another list of <T> elements that are represented by the identifiers described above.

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

I need to keep the same order in both collections, so the elements in the List<T> should be in the same position as in the first (due to errors in the search engines). And this process cannot be executed in the GetDocsFromDb() function.

If necessary, you can change the second list to some other structure (for example, Dictionary<long, T> ), but I would prefer not to change it.

Is there a simple and effective way to do this "sorting by some identifiers" with LINQ?

+105
collections sorting c # linq order
Mar 07 '13 at 15:36
source share
4 answers
 docs = docs.OrderBy(d => docsIds.IndexOf(d.Id)).ToList(); 
+261
Mar 07 '13 at 15:42
source share

Since you do not specify 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]; } } 

It is a common extension for what you want.

You can use the extension, for example,

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



A safer version might be

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

which will work if source doesn't loop exactly with order .

+13
Mar 07 '13 at 15:53
source share

Jodrell's answer is the best, but he actually redefined System.Linq.Enumerable.Join . Join also uses Lookup and preserves the source order.

  docIds.Join( docs, i => i, d => d.Id, (i, d) => d); 
-one
Apr 12 '19 at 11:11
source share

One simple approach is a zip with a sequencing sequence:

 List<T> docs = GetDocsFromDb(...).Zip(docIds, Tuple.Create) .OrderBy(x => x.Item2).Select(x => x.Item1).ToList(); 
-3
Mar 07 '13 at 15:44
source share



All Articles