public int CompareTo(MeasuredItem <TItem, TMeasure> other) { if (other == null) { return(-1); } var cmp = Measure.CompareTo(other.Measure); return(cmp != 0 ? cmp : _multiplier *Item.GetHashCode().CompareTo(other.Item.GetHashCode())); }
public static IEnumerable <TMeasurable> TopN <TMeasurable, TMeasure>(this IEnumerable <TMeasurable> items, TMeasurable reference, int k, SelectParallelOptions options = null) where TMeasure : IComparable <TMeasure> where TMeasurable : IMeasurable <TMeasurable, TMeasure> { if (options == null) { options = new SelectParallelOptions(); } MeasuredItem <TMeasurable, TMeasure>[] measuredItems; if (options.TaskCount == 1) { measuredItems = items.Select(item => new MeasuredItem <TMeasurable, TMeasure>(item, reference.Measure(item), true)) .ToArray(); } else { var itemsArray = items as TMeasurable[] ?? items.ToArray(); measuredItems = new MeasuredItem <TMeasurable, TMeasure> [itemsArray.Length]; // See http://www.codeproject.com/Articles/451628/Efficient-Map-Operations-for-Arrays-in-Csharp // Parallel.ForEach with range partitioner may be faster than other ways for > 10000 items. // It certainly was faster than using Task.Factory.StartNew and Task.WaitAll. Parallel.ForEach(Partitioner.Create(0, itemsArray.Length), range => { for (int i = range.Item1; i < range.Item2; ++i) { var item = itemsArray[i]; // ReSharper disable once AccessToModifiedClosure measuredItems[i] = new MeasuredItem <TMeasurable, TMeasure>(item, reference.Measure(item), true); } } ); } return(measuredItems .TopNParallel(k, null, options) .Select(measuredItem => measuredItem.Item) .Reverse() ); }