16
List<int> _lstNeedToOrder = new List<int>(); _lstNeedToOrder.AddRange(new int[] { 1, 5, 6, 8 }); //I need to sort this based on the below list. List<int> _lstOrdered = new List<int>();//to order by this list _lstOrdered.AddRange(new int[] { 13, 5, 11, 1, 4, 9, 2, 7, 12, 10, 3, 8, 6 }); order will be -->_lstNeedToOrder = 5,1,8,6 

How can I do it?

6 Answers 6

19

Well the simple - but inefficient - way would be:

var result = _lstNeedToOrder.OrderBy(x => _lstOrdered.IndexOf(x)); 

An alternative would be to work out a far way of obtaining the desired index of a value. If your values will always in be the range [1...n] you could just invert that "ordered" list to be a "list of indexes by value". At which point you could use:

var result = _lstNeedToOrder.OrderBy(x => indexes[x]); 

(where indexes would have an extra value at the start for 0, just to make things simpler).

Alternatively, you could create a Dictionary<int, int> from value to index. That would be more general, in that it would handle a very wide range of values without taking a lot of memory. But a dictionary lookup is obviously less efficient than an array or list lookup.

Just as a side note which wouldn't format well as a comment, your initialization can be simplified using a collection initializer:

var listToOrder = new List<int> { 1, 5, 6, 8 }; var orderedList = new List<int> { 13, 5, 11, 1, 4, 9, 2, 7, 12, 10, 3, 8, 6 }; 
Sign up to request clarification or add additional context in comments.

5 Comments

Hey Jon, sorry If it's a dumb question, but why is the first inefficient ?
@DimitarDimitrov: It uses IndexOf to find the desired index of each entry. That's an O(n) operation on the size of _lstOrdered, unnecessarily.
@DimitarDimitrov maybe because the use of IndexOf?
@JonSkeet Awkward Yep obviously ... oh well, that's very very embarrassing.
@JonSkeet, Thanks Jon! I wish I could be like you someday!
13
 List<int> results = _lstOrdered.Where(item => _lstNeedToOrder.Contains(item)).ToList(); 

3 Comments

Interesting idea. It wouldn't handle duplicates, but we don't know whether that's required of course.
Hm, I hadn't thought of that case. :) I guess it's up to the OP whether that's in the requirements or not.
@VaughanHilts, there will be no duplicates in my case, Thanks!
4

This works quite well:

var lookup = _lstOrdered .Select((x, n) => new { x, n }) .ToLookup(x => x.x, x => x.n); var query = from x in _lstNeedToOrder let rank = lookup[x] .DefaultIfEmpty(int.MaxValue) .First() orderby rank select x; 

Comments

4

You can build a custom comparer like this:

public class SequenceComparer<T> : IComparer<T> { private readonly Dictionary<T, int> indexes; public SequenceComparer(IEnumerable<T> sequence) { this.indexes = sequence .Select((item, index) => new { Item = item, Index = index }) .ToDictionary(x => x.Item, x => x.Index); } public int Compare(T x, T y) { return indexes[x].CompareTo(indexes[y]); } } 

Now you can say

var result = _lstNeedToOrder.OrderBy(x => x, new SequenceComparer(_lstOrdered)); 

2 Comments

how to use the class SequenceComparer<T>, I don't see how it's used in the OrderBy query.
@King King: Thanks. I missed creating it in the call to OrderBy. It's there now. Thanks again.
2

Another option is to use Intersect, which guarantees to return elements in the order in which they appear in the first sequence.

So, in this example

var result = _lstOrdered.Intersect(_lstNeedToOrder); 

yields { 5, 1, 8, 6} as required.

Comments

1

Saving in an intermediate dictionary the order...

// dict key will be the values of _lstOrdered, value will be the index of the // key in _lstOrdered // I'm using a seldom used .Select overload that returns the current value // plus its index (ix) var dict = _lstOrdered.Select((p, ix) => new { Value = p, Ix = ix }) .ToDictionary(p => p.Value, p => p.Ix); // note that this will explode if _lstNeedToOrder contains values outside // _lstOrdered. _lstNeedToOrder.Sort((p, q) => dict[p] - dict[q]); 

The .Sort method sorts in-place so _lstNeedToOrder will be ordered.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.