Sono riuscito a fare una versione più versatile, che consente di permutare più proprietà con un elenco di valori. È piuttosto sciocco (non usa LINQ, dato che i dati di input sono OrderedDictionary) e può essere migliorato se i dati di input sono in un formato più amichevole.
// hold index data for permutations
class IndexData
{
public int PropIndex { get; set; }
public int MaxCount { get; set; }
}
// input data - OrderedDictionary helps with the key order, but has serious non-typed drawbacks
var propsValues = new OrderedDictionary()
{
{ "colour", new List<String>() { "red", "blue", "violet", "black", "yellow"}},
{ "fruit", new List<String>() { "apple", "mango", "banana", "banana"}},
{ "vegetable", new List<String>() { "onion", "potato", "tomato"}},
{ "shape", new List<String>() { "round", "oval" }}
};
// compute index containers to help with permutations
var propsIndexes = new Dictionary<String, IndexData>();
var propsKeys = new List<String>();
foreach (var key in propsValues.Keys)
{
propsKeys.Add((String) key);
propsIndexes.Add((String) key, new IndexData() { PropIndex = 0, MaxCount = (propsValues[key] as List<String>).Count});
}
int propCount = propsValues.Count;
String lastKey = propsKeys[propCount - 1];
// count the permutations until the "most significant" property (the one changing least often) has reached its count
for (int combinationIndex = 0; ; combinationIndex ++ )
{
var sb = new StringBuilder();
sb.AppendFormat("{0}: ", combinationIndex + 1);
foreach (var key in propsValues.Keys)
{
int propIndex = propsIndexes[(String)key].PropIndex;
sb.AppendFormat("{0} ", ((propsValues[(String)key] as List<String>)[propIndex]));
}
Console.WriteLine(sb.ToString());
// incrementing indexes
bool exit = false;
propsIndexes[lastKey].PropIndex++;
for (int i = propCount - 1; i >= 0; i--)
{
String propKey = (String)propsKeys[i];
// current index has reached its count - incrementing previous one and resetting current one
if (propsIndexes[propKey].PropIndex >= propsIndexes[propKey].MaxCount)
{
propsIndexes[propKey].PropIndex = 0;
// "most significant" property has reached its count
if (i == 0)
{
exit = true;
break;
}
String prevPropKey = (String)propsKeys[i - 1];
propsIndexes[prevPropKey].PropIndex++;
}
}
if (exit)
break;
}