Cách tốt nhất để có được 10 bản ghi hàng đầu từ một bộ sưu tập rất lớn và sử dụng một OrderBy tùy chỉnh là gì? Nếu tôi sử dụng phương thức LINQ to Objects OrderBy thì nó sẽ chậm và mất rất nhiều bộ nhớ vì nó tạo ra một bộ sưu tập hoàn toàn mới với thứ tự mới. Tôi muốn một phương pháp mới với chữ ký bên dưới mà không sắp xếp lại các bộ sưu tập và rất nhanh:OrderBy and Top in LINQ với hiệu suất tốt
public static IEnumerable<TSource> OrderByTop<TSource, TKey>(
IEnumerable<TSource> source,
Func<TSource, TKey> keySelector,
IComparer<TKey> comparer,
int topCount)
tôi đã cố gắng để viết nó nhưng nó trở nên rất phức tạp và tôi nghĩ có thể có bất kỳ cách dễ dàng hơn bằng cách sử dụng tổng hợp hoặc một cái gì đó. Bất kỳ trợ giúp sẽ được đánh giá cao.
trả lời
Thanks for the help. Tôi đã kết thúc với đoạn mã sau:
public static List<TSource> OrderByTop<TSource, TKey>(
this IEnumerable<TSource> source,
Func<TSource, TKey> keySelector,
IComparer<TKey> comparer,
int topCount)
{
var itemComparer = keySelector.ToIComparer(comparer);
return source.Aggregate(
new List<TSource>(topCount),
(List<TSource> list, TSource item) =>
list.SortedInsert(item, itemComparer, topCount));
}
Phương pháp Danh sách mở rộng SortedInsert sau:
public static List<T> SortedInsert<T>(
this List<T> list,
T item,
IComparer<T> comparer,
int maxLength)
{
if (list.Count == maxLength)
if (comparer.Compare(item, list[maxLength - 1]) >= 0)
return list;
else
list.RemoveAt(maxLength - 1);
int insertIndex = list.BinarySearch(item, comparer);
if (insertIndex < 0)
insertIndex = ~insertIndex;
list.Insert(insertIndex, item);
return list;
}
Đối với những người quan tâm tôi cũng có phương pháp keySelector mở rộng chuyển đổi sang IComparer.
public static IComparer<TSource> ToIComparer<TSource, TKey>(
this Func<TSource, TKey> keySelector,
IComparer<TKey> comparer)
{
return new KeySelectorToIComparerConverter<TSource, TKey>(
keySelector,
comparer);
}
private class KeySelectorToIComparerConverter<TSource, TKey>
: IComparer<TSource>
{
private readonly IComparer<TKey> comparer;
private readonly Func<TSource, TKey> keySelector;
public KeySelectorToIComparerConverter(
Func<TSource, TKey> keySelector,
IComparer<TKey> comparer)
{
this.comparer = comparer;
this.keySelector = keySelector;
}
public int Compare(TSource x, TSource y)
{
return comparer.Compare(keySelector(x), keySelector(y));
}
}
IIRC SortedList ném một ngoại lệ khi khóa đã tồn tại. – Niki
Rất đẹp! Nó nên được RemoveAt (10) mặc dù và như nikie nói nó không chấp nhận các phím trùng lặp. – DRBlaise
Cảm ơn các gợi ý của bạn, tôi đã chỉnh sửa câu trả lời để phản ánh cả hai ... – MartinStettner