// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; using System.Linq; namespace osu.Framework.Extensions.IEnumerableExtensions { public static class EnumerableExtensions { /// /// Performs an action on all the items in an IEnumerable collection. /// /// The type of the items stored in the collection. /// The collection to iterate on. /// The action to be performed. public static void ForEach(this IEnumerable collection, Action action) { if (collection == null) return; foreach (var item in collection) action(item); } /// /// Wraps this object instance into an /// consisting of a single item. /// /// The type of the object. /// The instance that will be wrapped. /// An consisting of a single item. public static IEnumerable Yield(this T item) => new[] { item }; /// /// Retrieves the item after a pivot from an . /// /// The type of the items stored in the collection. /// The collection to iterate on. /// The pivot value. /// The item in appearing after , or null if no such item exists. public static T GetNext(this IEnumerable collection, T pivot) { return collection.SkipWhile(i => !EqualityComparer.Default.Equals(i, pivot)).Skip(1).FirstOrDefault(); } /// /// Retrieves the item before a pivot from an . /// /// The type of the items stored in the collection. /// The collection to iterate on. /// The pivot value. /// The item in appearing before , or null if no such item exists. public static T GetPrevious(this IEnumerable collection, T pivot) => collection.Reverse().GetNext(pivot); /// /// Returns the most common prefix of every string in this /// /// The string /// The most common prefix, or an empty string if no common prefix could be found. /// /// "ab" == { "abc", "abd" }.GetCommonPrefix() /// public static string GetCommonPrefix(this IEnumerable collection) { ReadOnlySpan prefix = default; foreach (var str in collection) { if (prefix.IsEmpty) // the first string { prefix = str; continue; } while (!prefix.IsEmpty) { if (str.AsSpan().StartsWith(prefix)) break; else prefix = prefix[..^1]; } if (prefix.IsEmpty) return string.Empty; } return new string(prefix); } /// /// Get all combinations of provided sequences. /// public static IEnumerable> CartesianProduct(this IEnumerable> sequences) { // https://stackoverflow.com/a/3098381 IEnumerable> emptyProduct = new[] { Enumerable.Empty() }; return sequences.Aggregate( emptyProduct, (accumulator, sequence) => from accseq in accumulator from item in sequence select accseq.Concat(new[] { item }) ); } } }