linq 查找一个项目的可能变体

lsmd5eda  于 2022-12-15  发布在  其他
关注(0)|答案(1)|浏览(154)

在我的应用程序中,我有配方的概念,每个配方都有可以被另一种成分替换的成分。我想做的是用每个成分生成每种可能性。我有以下结构作为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是可以相互替换的,因此,对于一个食谱来说,每个IngredientGroup都需要有一种配料。但是,由于我不知道IngredientGroup的数量,所以我无法通过迭代来找出每一种可能性。
例如,如果我事先知道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));
            }
}

我确信我在这里遗漏了一些东西。我如何在运行时生成每一种可能性?

tf7tbtn2

tf7tbtn21#

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

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

相关问题