0

在我的应用程序中,我有食谱的概念,每个食谱都有可以被另一种成分代替的成分。我想做的是用每种成分产生每一种可能性。我有以下结构作为 CLR 对象:

public class Food
{
    public Food()
    {
        NutritionalValues = new Collection<FoodNutritionalValue>();
    }

    public string Name { get; set; }
    public string Category { get; set; }

    public ICollection<FoodNutritionalValue> NutritionalValues { get; set; }
}

public class FoodNutritionalValue
{
    public string Type { get; set; }
    public decimal Value { get; set; }
}

public class Recipe
{
    public Recipe()
    {
        IngredientGroups = new Collection<IngredientGroup>();
    }

    public string Name { get; set; }
    public ICollection<IngredientGroup> IngredientGroups { get; set; }
}

public class IngredientGroup
{
    public IngredientGroup()
    {
        Ingredients = new Collection<Food>();
    }

    public ICollection<Food> Ingredients { get; set; }
}

IngredientGroup是可以互相替代的东西。因此,对于一个食谱,每个成分组都需要一种成分。但是,由于我不知道IngredientGroups计数,我无法遍历它们以找出每种可能性。

例如,如果我事先知道 IngredientGroups.Count 的计数,则以下代码可以正常工作

Recipe recipe2 = new Recipe();
IngredientGroup ingredientGroup3 = new IngredientGroup();
IngredientGroup ingredientGroup4 = new IngredientGroup();
IngredientGroup ingredientGroup5 = new IngredientGroup();

recipe2.Name = "Recipe2";
ingredientGroup3.Ingredients.Add(new Food { Name = "Food8", Category = "Categor8" });
ingredientGroup3.Ingredients.Add(new Food { Name = "Food9", Category = "Categor9" });

ingredientGroup4.Ingredients.Add(new Food { Name = "Food5", Category = "Categor5" });
ingredientGroup4.Ingredients.Add(new Food { Name = "Food10", Category = "Categor10" });
ingredientGroup4.Ingredients.Add(new Food { Name = "Food11", Category = "Category11" });

ingredientGroup5.Ingredients.Add(new Food { Name = "Food3", Category = "Categor3" });
ingredientGroup5.Ingredients.Add(new Food { Name = "Food4", Category = "Categor4" });

recipe2.IngredientGroups.Add(ingredientGroup3);
recipe2.IngredientGroups.Add(ingredientGroup4);
recipe2.IngredientGroups.Add(ingredientGroup5);

var recipes = new[] { recipe2 };

List<string> results = new List<string>();
foreach (var rcp in recipes)
{
    var group1 = rcp.IngredientGroups.ElementAt(0);
    var group2 = rcp.IngredientGroups.ElementAt(1);
    var group3 = rcp.IngredientGroups.ElementAt(2);

    foreach (var item1 in group1.Ingredients)
        foreach (var item2 in group2.Ingredients)
            foreach (var item3 in group3.Ingredients)
            {
                results.Add(string.Format("{0}, {1}, {2}", item1.Name, item2.Name, item3.Name));
            }
}

我确定我在这里遗漏了一些太大的东西。有人知道我如何在运行时产生所有可能性吗?

4

1 回答 1

1

根据找到的答案Here,您可能可以使用相同的辅助方法:

public static List<List<T>> CombinationsOf<T>(List<List<T>> sets)
{    
  var combinations = new List<List<T>>();

  foreach (var value in sets[0])
    combinations.Add(new List<T> { value });

  foreach (var set in sets.Skip(1))
    combinations = AddSet(combinations, set);

  return combinations;
}

private static List<List<T>> AddSet<T>(List<List<T>> combinations, List<T> set)
{
  var result = from value in set
               from combination in combinations
               select new List<T>(combination) { value };

  return result.ToList();
}

使用示例 (基于 OP 的示例)

...
var foods = recipes.SelectMany(recipe => 
  recipe.IngredientGroups.Select(ingredient =>
    ingredient.Ingredients.Select(o => o.Name).ToList()));

var results = from combination in CombinationsOf(foods.ToList())
              select string.Join(", ", combination);
...

输出

results :=

Food8, Food5, Food3 
Food9, Food5, Food3 
Food8, Food10, Food3 
Food9, Food10, Food3 
Food8, Food11, Food3 
Food9, Food11, Food3 
Food8, Food5, Food4 
Food9, Food5, Food4 
Food8, Food10, Food4 
Food9, Food10, Food4 
Food8, Food11, Food4 
Food9, Food11, Food4 
于 2014-02-07T19:31:44.807 回答