Не удивительно, что процесс медленный, потому что используемый вами алгоритм (с вложенным циклом) имеет как минимум квадратичную сложность времени O (N * N), которая при таком размере наборов данных действительно медленная.
Одним из способов является использование оператора LINQ GroupBy
, который внутренне использует поиск на основе хеша, следовательно, теоретически имеет O (N) временную сложность.Таким образом, вы группируете по type_id
и для каждой группы (список элементов с одинаковым ключом) выбираете одну с максимальным значением price
:
var uniqueBuyList = buyList
.GroupBy(e => e.type_id)
.Select(g => g.OrderByDescending(e => e.price).First())
.ToList();
Конечно, вам не нужно сортировать списокчтобы взять элемент с максимумом price
.Лучшей версией является использование метода Aggregate
(который в основном равен foreach
loop) для этого:
var uniqueBuyList = buyList
.GroupBy(e => e.type_id)
.Select(g => g.Aggregate((e1, e2) => e1.price > e2.price ? e1 : e2))
.ToList();
Другой способ, не основанный на LINQ, заключается в сортировке списка ввода по type_id
по возрастанию, price
по убыванию.Затем выполните один цикл над отсортированным списком и возьмите первый элемент каждой type_id
группы (он будет иметь максимум price
):
var comparer = Comparer<EveObjModel>.Create((e1, e2) =>
{
int result = e1.type_id.CompareTo(e2.type_id);
if (result == 0) // e1.type_id == e2.type_id
result = e2.price.CompareTo(e1.price); // e1, e2 exchanged to get descending order
return result;
});
buyList.Sort(comparer);
var uniqueBuyList = new List<EveObjModel>();
EveObjModel last = null;
foreach (var item in buyList)
{
if (last == null || last.type_id != item.type_id)
uniqueBuyList.Add(item);
last = item;
}
Сложность этого алгоритма равна O (N *log (N)), так что это хуже, чем алгоритмы на основе хеша (но намного лучше, чем оригинал).Преимущество состоит в том, что он использует меньше памяти, и результирующий список уже отсортирован по type_id
, поэтому вам не нужно использовать OrderBy
.