// I don't want all of MoreLINQ (https://github.com/morelinq/MoreLINQ) so we'll borrow just this #region License and Terms // MoreLINQ - Extensions to LINQ to Objects // Copyright (c) 2008 Jonathan Skeet. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #endregion using System; using System.Collections.Generic; namespace Artemis.Core { /// /// A static class providing extensions /// // ReSharper disable once InconsistentNaming public static class IEnumerableExtensions { /// /// Returns all distinct elements of the given source, where "distinctness" /// is determined via a projection and the default equality comparer for the projected type. /// /// /// This operator uses deferred execution and streams the results, although /// a set of already-seen keys is retained. If a key is seen multiple times, /// only the first element with that key is returned. /// /// Type of the source sequence /// Type of the projected element /// Source sequence /// Projection for determining "distinctness" /// /// A sequence consisting of distinct elements from the source sequence, /// comparing them by the specified key projection. /// public static IEnumerable DistinctBy(this IEnumerable source, Func keySelector) { return source.DistinctBy(keySelector, null!); } /// /// Returns all distinct elements of the given source, where "distinctness" /// is determined via a projection and the specified comparer for the projected type. /// /// /// This operator uses deferred execution and streams the results, although /// a set of already-seen keys is retained. If a key is seen multiple times, /// only the first element with that key is returned. /// /// Type of the source sequence /// Type of the projected element /// Source sequence /// Projection for determining "distinctness" /// /// The equality comparer to use to determine whether or not keys are equal. /// If null, the default equality comparer for TSource is used. /// /// /// A sequence consisting of distinct elements from the source sequence, /// comparing them by the specified key projection. /// public static IEnumerable DistinctBy(this IEnumerable source, Func keySelector, IEqualityComparer comparer) { if (source == null) throw new ArgumentNullException(nameof(source)); if (keySelector == null) throw new ArgumentNullException(nameof(keySelector)); return _(); IEnumerable _() { HashSet knownKeys = new(comparer); foreach (TSource element in source) { if (knownKeys.Add(keySelector(element))) yield return element; } } } /// /// Returns the index of the provided element inside the read only collection /// /// The type of element to find /// The collection to search in /// The element to find /// If found, the index of the element to find; otherwise -1 public static int IndexOf(this IReadOnlyCollection self, T elementToFind) { int i = 0; foreach (T element in self) { if (Equals(element, elementToFind)) return i; i++; } return -1; } } }