Sort one list by another

37,752

Solution 1

Another LINQ-approach:

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

Solution 2

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

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

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

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);
Share:
37,752
JGilmartin
Author by

JGilmartin

Contract IT Professional based in the UK specialising in Microsoft .NET core, Azure, DevOps, Docker, and MVC Web Development.

Updated on July 30, 2020

Comments

  • JGilmartin
    JGilmartin almost 4 years

    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.

  • Simon D.
    Simon D. over 13 years
    My personal experience is that Linq is in general performing much better than many people think, in most of the cases it's just syntactic sugar executing the same operations as other code in the end, so you will usually not feel the difference. Actually, for this special case I only know it works, I guess if it is not performing well then you will have to chose a completely different data structure, because this full list join will always take some time, no matter how you do it.
  • Justin Lang
    Justin Lang almost 11 years
    You are assuming that for each int in the order list, a corresponding Item will exist in the items list...
  • Boti
    Boti almost 11 years
    order.Where(d.ContainsKey).Select(...) or Select/SelectMany with a longer function that uses TryGetValue solves that issue.
  • Thorarin
    Thorarin over 7 years
    Important note: this requires the ints list to be sorted in the first place. The accepted answer does not.
  • nawfal
    nawfal over 7 years
    @Thorarin no I think. Why do you say that? We sort ints anyway to get the sort order, so it's not necessary ints have to be ordered in the first place.
  • nawfal
    nawfal over 7 years
    @Thorarin, something else is wrong then. I am sure about my code :)
  • Thorarin
    Thorarin over 7 years
    It definitely does not solve the problem that the OP describes. Your code never actually evaluates the ID properties of the objects. How can it possibly put stuff in the correct order?
  • nawfal
    nawfal over 7 years
    @Thorarin I made it clear in my answer that Join solves one kind of problem. Zip is for something else. The title goes by "sort a collection in the order of another collection" and for the vast majority it would imply what I went for in the answer. I just left an alternate answer that might help people with similar problem in future. Of course if sort is based on id, then an appropriate comparer has to be specified as well (in the OrderBy)
  • Bitterblue
    Bitterblue almost 7 years
    Any idea how to make this work for lists? I'm here because I have to work with lists and can't use this beautiful array sort thing.
  • Dima Kozhevin
    Dima Kozhevin almost 4 years
    Please don't post only code as answer, but also provide an explanation what your code does and how it solves the problem of the question. Answers with an explanation are usually more helpful and of better quality, and are more likely to attract upvotes.