Skip to content

Commit 921bf0f

Browse files
committed
EnumerableUtils.Combinations()
1 parent 48d1a13 commit 921bf0f

File tree

1 file changed

+39
-0
lines changed

1 file changed

+39
-0
lines changed

CSharp.Nixill/src/Utils/EnumerableUtils.cs

+39
Original file line numberDiff line numberDiff line change
@@ -418,6 +418,45 @@ public static IEnumerable<IEnumerable<T>> PermutationsDistinct<T>(this IEnumerab
418418
elemList.Add(elem);
419419
}
420420
}
421+
422+
// "limit" is non-optional here because 0 would just reutrn basically
423+
// the original list.
424+
//
425+
// Also, this immediately enumerates everything because otherwise it
426+
// would carry a risk of multiple enumeration.
427+
public static IEnumerable<IEnumerable<T>> Combinations<T>(this IEnumerable<T> elems, int limit)
428+
{
429+
T[] elemArray = elems.ToArray();
430+
431+
if (limit <= 0) limit += elemArray.Length;
432+
if (limit < 0) return Enumerable.Empty<IEnumerable<T>>();
433+
if (limit >= elemArray.Length) return EnumerableUtils.Of(elems);
434+
435+
return Combs(elemArray, limit);
436+
}
437+
438+
static IEnumerable<IEnumerable<T>> Combs<T>(IEnumerable<T> elemList, int keep)
439+
{
440+
int skips = elemList.Count() - keep;
441+
if (skips == 0)
442+
{
443+
yield return elemList;
444+
yield break;
445+
}
446+
447+
foreach ((T elem, int i) in elemList.Take(skips + 1).WithIndex())
448+
{
449+
if (keep == 1) yield return EnumerableUtils.Of(elem);
450+
else
451+
{
452+
foreach (IEnumerable<T> comb in Combs(elemList.Skip(i + 1), keep - 1))
453+
{
454+
yield return comb.Prepend(elem);
455+
}
456+
}
457+
}
458+
}
459+
421460
public static IEnumerable<T> Repeat<T>(this IEnumerable<T> seq, int count)
422461
{
423462
foreach (int i in Enumerable.Range(0, count))

0 commit comments

Comments
 (0)