1
0
Fork 0
mirror of https://github.com/Ellpeck/MLEM.git synced 2024-04-28 23:29:06 +02:00
MLEM/MLEM/Extensions/CollectionExtensions.cs

80 lines
4 KiB
C#

using System.Collections.Generic;
using System.Linq;
namespace MLEM.Extensions {
/// <summary>
/// A set of extensions for dealing with collections of various kinds
/// </summary>
public static class CollectionExtensions {
/// <summary>
/// This method returns a set of possible combinations of n items from n different sets, where the order of the items in each combination is based on the order of the input sets.
/// For a version of this method that returns indices rather than entries, see <see cref="IndexCombinations{T}"/>.
/// <example>
/// Given the input set <c>{{1, 2, 3}, {A, B}, {+, -}}</c>, the returned set would contain the following sets:
/// <code>
/// {1, A, +}, {1, A, -}, {1, B, +}, {1, B, -},
/// {2, A, +}, {2, A, -}, {2, B, +}, {2, B, -},
/// {3, A, +}, {3, A, -}, {3, B, +}, {3, B, -}
/// </code>
/// </example>
/// </summary>
/// <param name="things">The different sets to be combined</param>
/// <typeparam name="T">The type of the items in the sets</typeparam>
/// <returns>All combinations of set items as described</returns>
public static IEnumerable<IEnumerable<T>> Combinations<T>(this IEnumerable<IEnumerable<T>> things) {
var combos = Enumerable.Repeat(Enumerable.Empty<T>(), 1);
foreach (var t in things)
combos = combos.SelectMany(c => t.Select(c.Append));
return combos;
}
/// <summary>
/// This method returns a set of possible combinations of n indices of items from n different sets, where the order of the items' indices in each combination is based on the order of the input sets.
/// For a version of this method that returns entries rather than indices, see <see cref="Combinations{T}"/>.
/// <example>
/// Given the input set <c>{{1, 2, 3}, {A, B}, {+, -}}</c>, the returned set would contain the following sets:
/// <code>
/// {0, 0, 0}, {0, 0, 1}, {0, 1, 0}, {0, 1, 1},
/// {1, 0, 0}, {1, 0, 1}, {1, 1, 0}, {1, 1, 1},
/// {2, 0, 0}, {2, 0, 1}, {2, 1, 0}, {2, 1, 1}
/// </code>
/// </example>
/// </summary>
/// <param name="things">The different sets to be combined</param>
/// <typeparam name="T">The type of the items in the sets</typeparam>
/// <returns>All combinations of set items as described</returns>
public static IEnumerable<IEnumerable<int>> IndexCombinations<T>(this IEnumerable<IEnumerable<T>> things) {
var combos = Enumerable.Repeat(Enumerable.Empty<int>(), 1);
foreach (var t in things)
combos = combos.SelectMany(c => t.Select((o, i) => c.Append(i)));
return combos;
}
#if NET452
/// <summary>Appends a value to the end of the sequence.</summary>
/// <param name="source">A sequence of values.</param>
/// <param name="element">The value to append to <paramref name="source"/>.</param>
/// <typeparam name="T">The type of the elements of <paramref name="source"/>.</typeparam>
/// <returns>A new sequence that ends with <paramref name="element"/>.</returns>
public static IEnumerable<T> Append<T>(this IEnumerable<T> source, T element) {
foreach (var src in source)
yield return src;
yield return element;
}
/// <summary>Prepends a value to the beginning of the sequence.</summary>
/// <param name="source">A sequence of values.</param>
/// <param name="element">The value to prepend to <paramref name="source"/>.</param>
/// <typeparam name="T">The type of the elements of <paramref name="source"/>.</typeparam>
/// <returns>A new sequence that begins with <paramref name="element"/>.</returns>
public static IEnumerable<T> Prepend<T>(this IEnumerable<T> source, T element) {
yield return element;
foreach (var src in source)
yield return src;
}
#endif
}
}