I have a list of parameters that each accept a specific range of inputs. I am working on creating a test that creates every possible valid input. Furthermore, each group is optional (can be skipped entirely), so the combination lengths don't necessarily have to be the same length of the list.
Input
List<string[]> temp = new List<string[]>
{
// The order of these groups is important
new string[] { "a", "b", "c" },
new string[] { "d", "e" },
new string[] { "f", "g", "h" }
};
Constraints
- 0 or 1 item per group (a
string[]
above) - Order of the
List<T>
must be preserved
Valid Combinations
a, e, f
a, d, g
c, e, f
b, g
c, f
Invalid Combinations
a, b, f
(a
andb
are from the same group - not allowed)a, f, d
(wrong order -d
must come beforef
)
So far, I have gone back to my library where I have a Combinations LINQ method.
public static class IEnumerableExtensions
{
// Can be used to get all permutations at a certain level
// Source: http://stackoverflow.com/questions/127704/algorithm-to-return-all-combinations-of-k-elements-from-n#1898744
public static IEnumerable<IEnumerable<T>> Combinations<T>(this IEnumerable<T> elements, int k)
{
return k == 0 ? new[] { new T[0] } :
elements.SelectMany((e, i) =>
elements.Skip(i + 1).Combinations(k - 1).Select(c => (new[] { e }).Concat(c)));
}
}
In the past I have only used this on single sequence to do things like generate every permutation of URL segments. But I am struggling with its usage on a nested list with the constraints of one per group and in a specific order.
I know I can solve this particular puzzle by doing 3 nested loops and using lists to track which items were already used, but I don't know in advance how many items will be in the List<T>
, so that won't work in the general case.
How can I get all of the valid combinations of the above input?
I would prefer LINQ, but will accept any solution that solves this problem.