/// <summary>Returns the minimum value in a generic sequence according to a specified key selector function.</summary> /// <typeparam name="TSource">The type of the elements of <paramref name="source" />.</typeparam> /// <typeparam name="TKey">The type of key to compare elements by.</typeparam> /// <param name="source">A sequence of values to determine the minimum value of.</param> /// <param name="keySelector">A function to extract the key for each element.</param> /// <param name="comparer">The <see cref="IComparer{TKey}" /> to compare keys.</param> /// <returns>The value with the minimum key in the sequence.</returns> /// <exception cref="ArgumentNullException"><paramref name="source" /> is <see langword="null" />.</exception> /// <exception cref="ArgumentException">No key extracted from <paramref name="source" /> implements the <see cref="IComparable" /> or <see cref="IComparable{TKey}" /> interface.</exception> /// <remarks> /// <para>If <typeparamref name="TKey" /> is a reference type and the source sequence is empty or contains only values that are <see langword="null" />, this method returns <see langword="null" />.</para> /// </remarks> public static TSource?MinBy <TSource, TKey>(this IEnumerable <TSource> source, Func <TSource, TKey> keySelector, IComparer <TKey>?comparer) { if (source == null) { ThrowHelper.ThrowArgumentNullException(ExceptionArgument.source); } if (keySelector == null) { ThrowHelper.ThrowArgumentNullException(ExceptionArgument.keySelector); } comparer ??= Comparer <TKey> .Default; using IEnumerator <TSource> e = source.GetEnumerator(); if (!e.MoveNext()) { if (default(TSource) is null) { return(default);
public static long?Min(this IEnumerable <long?> source) { if (source == null) { ThrowHelper.ThrowArgumentNullException(ExceptionArgument.source); } long?value = null; using (IEnumerator <long?> e = source.GetEnumerator()) { do { if (!e.MoveNext()) { return(value); } value = e.Current; }while (!value.HasValue); long valueVal = value.GetValueOrDefault(); while (e.MoveNext()) { long?cur = e.Current; long x = cur.GetValueOrDefault(); // Do not replace & with &&. The branch prediction cost outweighs the extra operation // unless nulls either never happen or always happen. if (cur.HasValue & x < valueVal) { valueVal = x; value = cur; } } } return(value); }
public static long LongCount <TSource>(this IEnumerable <TSource> source) { if (source == null) { ThrowHelper.ThrowArgumentNullException(ExceptionArgument.source); } long count = 0; using (IEnumerator <TSource> e = source.GetEnumerator()) { checked { while (e.MoveNext()) { count++; } } } return(count); }
public static Dictionary <TKey, TElement> ToDictionary <TSource, TKey, TElement>(IEnumerable <TSource> source, Func <TSource, TKey> keySelector, Func <TSource, TElement> elementSelector, IEqualityComparer <TKey> comparer) { if (source == null) { throw ThrowHelper.ArgumentNull("source"); } if (keySelector == null) { throw ThrowHelper.ArgumentNull("keySelector"); } if (elementSelector == null) { throw ThrowHelper.ArgumentNull("elementSelector"); } Dictionary <TKey, TElement> tKeys = new Dictionary <TKey, TElement>(comparer); foreach (TSource tSource in source) { tKeys.Add(keySelector(tSource), elementSelector(tSource)); } return(tKeys); }
public static TSource Single <TSource>(this IEnumerable <TSource> source) { if (source == null) { ThrowHelper.ThrowArgumentNullException(ExceptionArgument.source); } if (source is IList <TSource> list) { switch (list.Count) { case 0: ThrowHelper.ThrowNoElementsException(); return(default); case 1: return(list[0]); } } else { using (IEnumerator <TSource> e = source.GetEnumerator()) { if (!e.MoveNext()) { ThrowHelper.ThrowNoElementsException(); } TSource result = e.Current; if (!e.MoveNext()) { return(result); } } } ThrowHelper.ThrowMoreThanOneElementException(); return(default);
public static double Min(this IEnumerable <double> source) { if (source == null) { ThrowHelper.ThrowArgumentNullException(ExceptionArgument.source); } double value; using (IEnumerator <double> e = source.GetEnumerator()) { if (!e.MoveNext()) { ThrowHelper.ThrowNoElementsException(); } value = e.Current; if (double.IsNaN(value)) { return(value); } while (e.MoveNext()) { double x = e.Current; if (x < value) { value = x; } else if (double.IsNaN(x)) { return(x); } } } return(value); }
public static int Count <TSource>(this IEnumerable <TSource> source) { if (source == null) { ThrowHelper.ThrowArgumentNullException(ExceptionArgument.source); } if (source is ICollection <TSource> collectionoft) { return(collectionoft.Count); } if (source is IIListProvider <TSource> listProv) { return(listProv.GetCount(onlyIfCheap: false)); } if (source is ICollection collection) { return(collection.Count); } int count = 0; using (IEnumerator <TSource> e = source.GetEnumerator()) { checked { while (e.MoveNext()) { count++; } } } return(count); }
public static decimal?Min(this IEnumerable <decimal?> source) { if (source == null) { ThrowHelper.ThrowArgumentNullException(ExceptionArgument.source); } decimal?value = null; using (IEnumerator <decimal?> e = source.GetEnumerator()) { do { if (!e.MoveNext()) { return(value); } value = e.Current; }while (!value.HasValue); decimal valueVal = value.GetValueOrDefault(); while (e.MoveNext()) { decimal?cur = e.Current; decimal x = cur.GetValueOrDefault(); if (cur.HasValue && x < valueVal) { valueVal = x; value = cur; } } } return(value); }
/// <summary>Returns the minimum value in a generic sequence.</summary> /// <typeparam name="TSource">The type of the elements of <paramref name="source" />.</typeparam> /// <param name="source">A sequence of values to determine the minimum value of.</param> /// <param name="comparer">The <see cref="IComparer{T}" /> to compare values.</param> /// <returns>The minimum value in the sequence.</returns> /// <exception cref="ArgumentNullException"><paramref name="source" /> is <see langword="null" />.</exception> /// <exception cref="ArgumentException">No object in <paramref name="source" /> implements the <see cref="System.IComparable" /> or <see cref="System.IComparable{T}" /> interface.</exception> /// <remarks> /// <para>If type <typeparamref name="TSource" /> implements <see cref="System.IComparable{T}" />, the <see cref="Max{T}(IEnumerable{T})" /> method uses that implementation to compare values. Otherwise, if type <typeparamref name="TSource" /> implements <see cref="System.IComparable" />, that implementation is used to compare values.</para> /// <para>If <typeparamref name="TSource" /> is a reference type and the source sequence is empty or contains only values that are <see langword="null" />, this method returns <see langword="null" />.</para> /// <para>In Visual Basic query expression syntax, an `Aggregate Into Max()` clause translates to an invocation of <see cref="O:Enumerable.Max" />.</para> /// </remarks> public static TSource?Min <TSource>(this IEnumerable <TSource> source, IComparer <TSource>?comparer) { if (source == null) { ThrowHelper.ThrowArgumentNullException(ExceptionArgument.source); } comparer ??= Comparer <TSource> .Default; TSource?value = default; using (IEnumerator <TSource> e = source.GetEnumerator()) { if (value == null) { do { if (!e.MoveNext()) { return(value); } value = e.Current; }while (value == null); while (e.MoveNext()) { TSource next = e.Current; if (next != null && comparer.Compare(next, value) < 0) { value = next; } } } else { if (!e.MoveNext()) { ThrowHelper.ThrowNoElementsException(); } value = e.Current; if (comparer == Comparer <TSource> .Default) { while (e.MoveNext()) { TSource next = e.Current; if (Comparer <TSource> .Default.Compare(next, value) < 0) { value = next; } } } else { while (e.MoveNext()) { TSource next = e.Current; if (comparer.Compare(next, value) < 0) { value = next; } } } } } return(value); }
void IList <TElement> .RemoveAt(int index) => ThrowHelper.ThrowNotSupportedException();
void IList <TElement> .Insert(int index, TElement item) => ThrowHelper.ThrowNotSupportedException();
bool ICollection <TElement> .Remove(TElement item) { ThrowHelper.ThrowNotSupportedException(); return(false); }
void ICollection <TElement> .Clear() => ThrowHelper.ThrowNotSupportedException();
void ICollection <TElement> .Add(TElement item) => ThrowHelper.ThrowNotSupportedException();
private static IEnumerable <TSource> ElementsInIterator <TSource>(IEnumerable <TSource> source, Range range) { Index start = range.Start; Index end = range.End; if (source is IList <TSource> list) { int count = list.Count; if (count == 0 && range.Equals(System.Range.All)) { yield break; } int firstIndex = start.IsFromEnd ? count - start.Value : start.Value; int lastIndex = (end.IsFromEnd ? count - end.Value : end.Value) - 1; if (lastIndex < firstIndex - 1) { ThrowHelper.ThrowOverflowException(); // Following the behavior of array with range. } if (firstIndex < 0 || lastIndex < 0) { ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.range); // Following the behavior of array with range. } if (firstIndex >= count || lastIndex >= count) { ThrowHelper.ThrowArgumentException(ExceptionArgument.range); // Following the behavior of array with range. } for (int currentIndex = firstIndex; currentIndex <= lastIndex; currentIndex++) { yield return(list[currentIndex]); } yield break; } using (IEnumerator <TSource> e = source.GetEnumerator()) { int currentIndex = -1; if (start.IsFromEnd) { if (!e.MoveNext()) { const int count = 0; int firstIndex = count - start.Value; int lastIndex = (end.IsFromEnd ? count - end.Value : end.Value) - 1; if (lastIndex < firstIndex - 1) { ThrowHelper.ThrowOverflowException(); // Following the behavior of array with range. } ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.range); // Following the behavior of array with range. } else { Queue <TSource> queue = new Queue <TSource>(); queue.Enqueue(e.Current); currentIndex++; int takeLastCount = start.Value; while (e.MoveNext()) { if (queue.Count == takeLastCount) { queue.Dequeue(); } queue.Enqueue(e.Current); currentIndex++; } if (queue.Count < takeLastCount) { ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.range); // Following the behavior of array with range. } int firstIndex = currentIndex + 1 - takeLastCount; int lastIndex = end.IsFromEnd ? currentIndex - end.Value : end.Value - 1; if (lastIndex < firstIndex - 1) { ThrowHelper.ThrowOverflowException(); // Following the behavior of array with range. } for (int index = firstIndex; index <= lastIndex; index++) { yield return(queue.Dequeue()); } } } else { int firstIndex = start.Value; if (!e.MoveNext()) { if (range.Equals(System.Range.All)) { yield break; } const int count = 0; int lastIndex = (end.IsFromEnd ? count - end.Value : end.Value) - 1; if (lastIndex < firstIndex - 1) { ThrowHelper.ThrowOverflowException(); // Following the behavior of array with range. } ThrowHelper.ThrowArgumentException(ExceptionArgument.range); // Following the behavior of array with range. } currentIndex++; while (currentIndex < firstIndex && e.MoveNext()) { currentIndex++; } if (currentIndex != firstIndex) { ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.range); // Following the behavior of array with range. } if (end.IsFromEnd) { int skipLastCount = end.Value; if (skipLastCount > 0) { Queue <TSource> queue = new Queue <TSource>(); do { if (queue.Count == skipLastCount) { yield return(queue.Dequeue()); } queue.Enqueue(e.Current); currentIndex++; }while (e.MoveNext()); } else { do { yield return(e.Current); currentIndex++; }while (e.MoveNext()); } if (firstIndex + skipLastCount > currentIndex) { ThrowHelper.ThrowOverflowException(); // Following the behavior of array with range. } } else { int lastIndex = end.Value - 1; if (lastIndex < firstIndex - 1) { ThrowHelper.ThrowOverflowException(); // Following the behavior of array with range. } if (lastIndex == firstIndex - 1) { yield break; } yield return(e.Current); while (currentIndex < lastIndex && e.MoveNext()) { currentIndex++; yield return(e.Current); } if (currentIndex != lastIndex) { ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.range); // Following the behavior of array with range. } } } } }