A game framework written with osu! in mind.
at master 4.6 kB view raw
1// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. 2// See the LICENCE file in the repository root for full licence text. 3 4using System; 5using System.Collections.Generic; 6using System.Linq; 7 8namespace osu.Framework.Extensions.IEnumerableExtensions 9{ 10 public static class EnumerableExtensions 11 { 12 /// <summary> 13 /// Performs an action on all the items in an IEnumerable collection. 14 /// </summary> 15 /// <typeparam name="T">The type of the items stored in the collection.</typeparam> 16 /// <param name="collection">The collection to iterate on.</param> 17 /// <param name="action">The action to be performed.</param> 18 public static void ForEach<T>(this IEnumerable<T> collection, Action<T> action) 19 { 20 if (collection == null) return; 21 22 foreach (var item in collection) 23 action(item); 24 } 25 26 /// <summary> 27 /// Wraps this object instance into an <see cref="IEnumerable{T}"/> 28 /// consisting of a single item. 29 /// </summary> 30 /// <typeparam name="T">The type of the object.</typeparam> 31 /// <param name="item">The instance that will be wrapped.</param> 32 /// <returns> An <see cref="IEnumerable{T}"/> consisting of a single item.</returns> 33 public static IEnumerable<T> Yield<T>(this T item) => new[] { item }; 34 35 /// <summary> 36 /// Retrieves the item after a pivot from an <see cref="IEnumerable{T}"/>. 37 /// </summary> 38 /// <typeparam name="T">The type of the items stored in the collection.</typeparam> 39 /// <param name="collection">The collection to iterate on.</param> 40 /// <param name="pivot">The pivot value.</param> 41 /// <returns>The item in <paramref name="collection"/> appearing after <paramref name="pivot"/>, or null if no such item exists.</returns> 42 public static T GetNext<T>(this IEnumerable<T> collection, T pivot) 43 { 44 return collection.SkipWhile(i => !EqualityComparer<T>.Default.Equals(i, pivot)).Skip(1).FirstOrDefault(); 45 } 46 47 /// <summary> 48 /// Retrieves the item before a pivot from an <see cref="IEnumerable{T}"/>. 49 /// </summary> 50 /// <typeparam name="T">The type of the items stored in the collection.</typeparam> 51 /// <param name="collection">The collection to iterate on.</param> 52 /// <param name="pivot">The pivot value.</param> 53 /// <returns>The item in <paramref name="collection"/> appearing before <paramref name="pivot"/>, or null if no such item exists.</returns> 54 public static T GetPrevious<T>(this IEnumerable<T> collection, T pivot) 55 => collection.Reverse().GetNext(pivot); 56 57 /// <summary> 58 /// Returns the most common prefix of every string in this <see cref="IEnumerable{T}"/> 59 /// </summary> 60 /// <param name="collection">The string <see cref="IEnumerable{T}"/></param> 61 /// <returns>The most common prefix, or an empty string if no common prefix could be found.</returns> 62 /// <example> 63 /// "ab" == { "abc", "abd" }.GetCommonPrefix() 64 /// </example> 65 public static string GetCommonPrefix(this IEnumerable<string> collection) 66 { 67 ReadOnlySpan<char> prefix = default; 68 69 foreach (var str in collection) 70 { 71 if (prefix.IsEmpty) // the first string 72 { 73 prefix = str; 74 continue; 75 } 76 77 while (!prefix.IsEmpty) 78 { 79 if (str.AsSpan().StartsWith(prefix)) 80 break; 81 else 82 prefix = prefix[..^1]; 83 } 84 85 if (prefix.IsEmpty) 86 return string.Empty; 87 } 88 89 return new string(prefix); 90 } 91 92 /// <summary> 93 /// Get all combinations of provided sequences. 94 /// </summary> 95 public static IEnumerable<IEnumerable<T>> CartesianProduct<T>(this IEnumerable<IEnumerable<T>> sequences) 96 { 97 // https://stackoverflow.com/a/3098381 98 IEnumerable<IEnumerable<T>> emptyProduct = new[] { Enumerable.Empty<T>() }; 99 return sequences.Aggregate( 100 emptyProduct, 101 (accumulator, sequence) => 102 from accseq in accumulator 103 from item in sequence 104 select accseq.Concat(new[] { item }) 105 ); 106 } 107 } 108}