web-dev-qa-db-fra.com

Trier une liste par une autre

J'ai 2 objets de liste, l'un est juste une liste d'entiers, l'autre est une liste d'objets mais les objets ont une propriété ID.

Ce que je veux faire, c'est trier la liste des objets par son ID dans le même ordre de tri que la liste des entrées.

Je joue depuis un moment maintenant essayant de le faire fonctionner, jusqu'à présent pas de joie,

Voici ce que j'ai jusqu'à présent ...

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

L'intérêt est que lorsqu'un utilisateur recherche des membres, ils s'affichent d'abord dans un ordre aléatoire, puis s'ils cliquent sur la page 2, ils restent dans cet ordre et les 20 résultats suivants s'affichent.

J'ai lu sur l'ICompare que je peux utiliser comme paramètre dans la clause Linq.OrderBy, mais je ne trouve aucun exemple simple.

J'espère une solution de style LINQ élégante et très simple, et je peux toujours espérer.

Toute aide est très appréciée.

72
JGilmartin

Une autre approche LINQ:

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

Une façon de le faire:

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

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

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

Pas une réponse à cette exacte question, mais si vous avez deux tableaux, il y a une surcharge de Array.Sort qui prend le tableau à trier et un tableau à utiliser comme "clé"

https://msdn.Microsoft.com/en-us/library/85y6y2d3.aspx

Méthode Array.Sort (Array, Array)
Trie une paire d'objets de tableau unidimensionnels (l'un contient les clés et l'autre contient les éléments correspondants) en fonction des clés du premier tableau à l'aide de l'implémentation IComparable de chaque clé.

13
Mark Sowul

Join est le meilleur candidat si vous voulez faire correspondre le nombre entier exact (si aucune correspondance n'est trouvée, vous obtenez une séquence vide). Si vous voulez simplement obtenir l'ordre de tri de l'autre liste (et à condition que le nombre d'éléments dans les deux listes soit égal), vous pouvez utiliser Zip .

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

Assez lisible.

9
nawfal

Voici une méthode d'extension qui encapsule réponse de Simon D. pour les listes de tout 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);
}

L'utilisation est quelque chose comme:

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

Une solution possible:

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

Remarque: utilisez-le si vous travaillez avec In-Memory répertorie, ne fonctionne pas pour le type IQueryable, car IQueryable ne contient pas de définition pour IndexOf

0
Mehdi Dehghani