Ответ 1
Другой подход LINQ:
var orderedByIDList = from i in ids
join o in objectsWithIDs
on i equals o.ID
select o;
У меня есть 2 объекта списка, один - только список int, другой - список объектов, но объекты имеют свойство ID.
Что я хочу сделать, так это отсортировать список объектов по его идентификатору в том же порядке сортировки, что и список int.
Я играл некоторое время, пытаясь заставить его работать, до сих пор нет радости,
Вот что я до сих пор...
//**************************
//*** 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, и я всегда надеюсь.
Любая помощь наиболее ценится.
Другой подход LINQ:
var orderedByIDList = from i in ids
join o in objectsWithIDs
on i equals o.ID
select o;
Один из способов сделать это:
List<int> order = ....;
List<Item> items = ....;
Dictionary<int,Item> d = items.ToDictionary(x => x.ID);
List<Item> ordered = order.Select(i => d[i]).ToList();
Не ответ на этот точный вопрос, но если у вас есть два массива, существует перегрузка Array.Sort
, которая берет массив для сортировки и массив для использования в качестве "ключа"
https://msdn.microsoft.com/en-us/library/85y6y2d3.aspx
Array.Sort Method (массив, массив)
Сортирует пару одномерных объектов Array (один содержит ключи а другой содержит соответствующие элементы) на основе ключей в первый массив с использованием IComparable реализации каждого ключа.
Join
является лучшим кандидатом, если вы хотите совместить точное целое число (если совпадение не найдено, вы получаете пустую последовательность). Если вы хотите просто получить порядок сортировки другого списка (при условии, что количество элементов в обоих списках равно), вы можете использовать "Zip" .
var result = objects.Zip(ints, (o, i) => new { o, i})
.OrderBy(x => x.i)
.Select(x => x.o);
Довольно читаемый.
Вот метод расширения, который инкапсулирует ответ Саймона Д. для списков любого типа.
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);
Одно из возможных решений:
myList = myList.OrderBy(x => Ids.IndexOf(x.Id)).ToList();
Примечание: используйте это, если вы работаете с списками In-Memory
, не работает для типа IQueryable
, так как IQueryable
не содержит определения для IndexOf