Sort one list by another

C#LinqListSorting

C# Problem Overview


I have 2 list objects, one is just a list of ints, the other is a list of objects but the objects has an ID property.

What i want to do is sort the list of objects by its ID in the same sort order as the list of ints.

Ive been playing around for a while now trying to get it working, so far no joy,

Here is what i have so far...

//**************************
//*** Randomize the list ***
//**************************
if (Session["SearchResultsOrder"] != null)
{
    // save the session as a int list
    List<int> IDList = new List<int>((List<int>)Session["SearchResultsOrder"]);
    // the saved list session exists, make sure the list is orded by this
    foreach(var i in IDList)
    {
        SearchData.ReturnedSearchedMembers.OrderBy(x => x.ID == i);
    }
}
else
{
    // before any sorts randomize the results - this mixes it up a bit as before it would order the results by member registration date                        
    List<Member> RandomList = new List<Member>(SearchData.ReturnedSearchedMembers);
    SearchData.ReturnedSearchedMembers = GloballyAvailableMethods.RandomizeGenericList<Member>(RandomList, RandomList.Count).ToList();

    // save the order of these results so they can be restored back during postback
    List<int> SearchResultsOrder = new List<int>();
    SearchData.ReturnedSearchedMembers.ForEach(x => SearchResultsOrder.Add(x.ID));
    Session["SearchResultsOrder"] = SearchResultsOrder;
}   

The whole point of this is so when a user searches for members, initially they display in a random order, then if they click page 2, they remain in that order and the next 20 results display.

I have been reading about the ICompare i can use as a parameter in the Linq.OrderBy clause, but i can’t find any simple examples.

I’m hoping for an elegant, very simple LINQ style solution, well I can always hope.

Any help is most appreciated.

C# Solutions


Solution 1 - C#

Another LINQ-approach:

 var orderedByIDList = from i in ids 
                       join o in objectsWithIDs
                       on i equals o.ID
                       select o;

Solution 2 - C#

One way of doing it:

List<int>  order = ....;
List<Item> items = ....;

Dictionary<int,Item> d = items.ToDictionary(x => x.ID);

List<Item> ordered = order.Select(i => d[i]).ToList();

Solution 3 - C#

Not an answer to this exact question, but if you have two arrays, there is an overload of Array.Sort that takes the array to sort, and an array to use as the 'key'

https://msdn.microsoft.com/en-us/library/85y6y2d3.aspx > Array.Sort Method (Array, Array)
> Sorts a pair of one-dimensional Array objects (one contains the keys > and the other contains the corresponding items) based on the keys in > the first Array using the IComparable implementation of each key.

Solution 4 - C#

Join is the best candidate if you want to match on the exact integer (if no match is found you get an empty sequence). If you want to merely get the sort order of the other list (and provided the number of elements in both lists are equal), you can use Zip.

var result = objects.Zip(ints, (o, i) => new { o, i})
                    .OrderBy(x => x.i)
                    .Select(x => x.o);

Pretty readable.

Solution 5 - C#

Here is an extension method which encapsulates Simon D.'s response for lists of any type.

public static IEnumerable<TResult> SortBy<TResult, TKey>(this IEnumerable<TResult> sortItems,
                                                         IEnumerable<TKey> sortKeys,
                                                         Func<TResult, TKey> matchFunc)
{
    return sortKeys.Join(sortItems,
                         k => k,
                         matchFunc,
                         (k, i) => i);
}

Usage is something like:

var sorted = toSort.SortBy(sortKeys, i => i.Key);

Solution 6 - C#

One possible solution:

myList = myList.OrderBy(x => Ids.IndexOf(x.Id)).ToList();

Note: use this if you working with In-Memory lists, doesn't work for IQueryable type, as IQueryable does not contain a definition for IndexOf

Solution 7 - C#

docs = docs.OrderBy(d => docsIds.IndexOf(d.Id)).ToList();

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJGilmartinView Question on Stackoverflow
Solution 1 - C#Simon D.View Answer on Stackoverflow
Solution 2 - C#JimmyView Answer on Stackoverflow
Solution 3 - C#Mark SowulView Answer on Stackoverflow
Solution 4 - C#nawfalView Answer on Stackoverflow
Solution 5 - C#gregsdennisView Answer on Stackoverflow
Solution 6 - C#Mehdi DehghaniView Answer on Stackoverflow
Solution 7 - C#Sanish ThomasView Answer on Stackoverflow