If you first convert dictionaries into containers, it seems you can get the desired result using the Cartesian product.
var containers = new List<Dictionary<string, IEnumerable<string>>> { new Dictionary<string, IEnumerable<string>>() {{"Pie", new [] {"Raspberry", "Strawbery"}}}, new Dictionary<string, IEnumerable<string>>() {{"Drink", new [] {"Cola", "Coffee"}}}, new Dictionary<string, IEnumerable<string>>() {{"Bread", new [] {"Bagel", "Pretzel", "Scone"}}}, }; var flatten = containers.Select(dict => dict.SelectMany(c => c.Value.Select(v => new {type = c.Key, name = v}))); foreach (var combo in CartesianProduct(flatten)) { Console.WriteLine(string.Join(", ", combo.Select(c => c.type + ": " + c.name))); }
Cartesian product method from fooobar.com/questions/9159 / ...
public static IEnumerable<IEnumerable<T>> CartesianProduct<T>(IEnumerable<IEnumerable<T>> sequences) { IEnumerable<IEnumerable<T>> emptyProduct = new[] { Enumerable.Empty<T>() }; return sequences.Aggregate( emptyProduct, (accumulator, sequence) => from accseq in accumulator from item in sequence select accseq.Concat(new[] {item}) ); }
Output:
Pie: Raspberry, Drink: Cola, Bread: Bagel Pie: Raspberry, Drink: Cola, Bread: Pretzel Pie: Raspberry, Drink: Cola, Bread: Scone Pie: Raspberry, Drink: Coffee, Bread: Bagel Pie: Raspberry, Drink: Coffee, Bread: Pretzel Pie: Raspberry, Drink: Coffee, Bread: Scone Pie: Strawbery, Drink: Cola, Bread: Bagel Pie: Strawbery, Drink: Cola, Bread: Pretzel Pie: Strawbery, Drink: Cola, Bread: Scone Pie: Strawbery, Drink: Coffee, Bread: Bagel Pie: Strawbery, Drink: Coffee, Bread: Pretzel Pie: Strawbery, Drink: Coffee, Bread: Scone