2010-10-15 124 views
68

我有2個列表對象,其中一個是整數列表,另一個是對象列表,但對象具有ID屬性。排序一個列表另一個

我想要做的就是按照與整數列表相同的排序順序對它的ID列表進行排序。

我一直玩了一段時間,現在試圖得到它的工作,到目前爲止,還沒有喜悅,

這裏是我迄今爲止...

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

這樣做的整點因此當用戶搜索會員時,最初他們以隨機順序顯示,然後如果他們點擊第2頁,他們將保持該順序,並顯示下20個結果。

我一直在閱讀有關ICompare我可以用作Linq.OrderBy子句中的參數,但我找不到任何簡單的示例。

我希望有一個優雅,非常簡單的LINQ風格的解決方案,以及我一直希望的。

任何幫助最受讚賞。這樣做的

+4

你有沒有考慮在兩個列表之間執行linq連接,然後進行排序? – RQDQ 2010-10-15 20:39:03

+0

提示:您需要將原始順序保存爲字典:id 2索引。 – 2010-10-15 20:40:06

+3

http://stackoverflow.com/questions/3470098/linq-list-sort-based-on-another-list – goodeye 2012-11-28 00:11:42

回答

116

另一個LINQ的方法:

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

性能如何? – 2010-10-15 21:16:19

+7

我個人的經驗是Linq總體來說表現比許多人想象的要好得多,在大多數情況下,它只是語法糖最後執行與其他代碼相同的操作,所以你通常不會感覺到差異。 其實,對於這種特殊情況,我只知道它的工作原理,我猜如果它表現不好,那麼你將不得不選擇一個完全不同的數據結構,因爲這個完整列表連接總是需要一些時間,不管你怎麼做。 – 2010-10-16 18:50:30

24

方式一:

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

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

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

可能的重複您假設對於訂單列表中的每個int,項目中將存在相應的項目list ... – 2013-05-21 22:17:38

+1

'order.Where(d.ContainsKey).Select(...)'或Select/SelectMany使用TryGetValue更長的函數解決了這個問題。 – Jimmy 2013-05-21 22:57:09

9

Join是最佳人選,如果你想匹配確切的整數(如果沒有找到匹配您獲得一個空序列)。如果您只想獲得其他列表的排序順序(並且提供的兩個列表中的元素數量相同),則可以使用Zip

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

很可讀。

+0

重要提示:這需要首先對ints列表進行排序。接受的答案不是。 – Thorarin 2016-09-28 13:54:39

+0

@Thorarin不,我想。你爲什麼這麼說?我們對ints進行排序以得到排序順序,因此不必首先對整數進行排序。 – nawfal 2016-09-28 13:57:36

+0

@Thorarin,那麼別的東西是錯誤的。我確信我的代碼:) – nawfal 2016-09-28 14:17:40

4

這是一個擴展方法,它爲任何類型的列表封裝Simon D.'s response

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

用法是一樣的東西:

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

不回答這個確切的問題,但如果你有兩個陣列,有可能採取的數組進行排序的Array.Sort超載,以及用作'鑰匙'的陣列

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

的Array.Sort方法(Array,陣列)
對一對一維數組(一個包含鍵 ,另一個包含對應的項目)的基礎上的鑰匙, 使用所述第一陣列每個密鑰的IComparable實現。

+0

任何想法如何使這個工作的列表?我在這裏**因爲**我必須使用列表,不能使用這個漂亮的數組排序的東西。 – Bitterblue 2017-08-11 08:43:50

0

一個可能的解決方案:

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

注:使用這​​個,如果你用In-Memory名單的工作,不適合IQueryable類型的工作,因爲IQueryable不包含定義IndexOf