如何使用let在LINQ查询中定义一组新数据?

时间:2013-04-18 01:25:22

标签: c# linq

我有一个代表食谱所有成分的课程

public class ViewRecipe
{
    public string RecipeName { get; set; }
    public string IngredientName { get; set; }
    public double UnitWeight { get; set; }
    public double TotalWeight { get; set; }

    public ViewRecipe() { }
    public ViewRecipe(string _RecipeName, string _IngredientName, double _UnitWeight, double _TotalWeight)
    {
        RecipeName = _RecipeName;
        IngredientName = _IngredientName;
        UnitWeight = _UnitWeight;
        TotalWeight = _TotalWeight;
    }
}(in reality there are a LOT more data members like quantity, weight, etc....)

实际数据集是名为ViewRecipeSummary的List,它看起来像这样:

RecipeName IngredientName
1          A
1          B
1          C
2          D
2          E
3          A
3          Z

我有一个查找INGRIDENT(recipeGroup.Key)的现有查询,我现在需要执行以下操作:

1-找到所有含有该成分的食谱

2-从我的数据中返回这些食谱的所有行

然后我需要在我的查询中使用它(所以它需要使用LET或其他东西)

让我们假设我正在寻找共享成分A的所有食谱,我希望我的LET的最终结果(基于我上面显示的数据)看起来完全像这样:

RecipeName IngredientName
1          A
1          B
1          C
3          A
3          Z

因此,对于任何含有成分A(1和3)的食谱,都会返回这些食谱的所有行,这样我就拥有了我需要的所有成分。 这应该与我的ViewRecipe类相同(不是一些新的{RecipeName,List}等等),它应该以相同的格式提供相同的数据行。

当前LINQ查询:

            ViewFullRecipeGrouping = (
                from data in ViewRecipeSummary
                group data by data.RecipeName into recipeGroup
                let fullIngredientGroups = recipeGroup.GroupBy(x => x.IngredientName)
                select new ViewFullRecipe()
                {
                    RecipeName = recipeGroup.Key,
                    RecipeIngredients = (
                        from ingredientGroup in fullIngredientGroups
                        select new GroupIngredient()
                        {
                            IngredientName = ingredientGroup.Key,
                        }
                    ).ToList(),
                    ViewGroupRecipes = (

            // THIS IS WHERE I NEED TO ADD MY CODE SO THAT I CAN USE THE RESULT BELOW
            let a = .....
            // BUT I HAVE NO CLUE HOW TO PERFORM SUCH A QUERY HERE

                        select new GroupRecipe()
                        {
            // USE THE RESULTS FOUND TO GENERATE MY RECIPE GROUP
            // BASED ON THE RESULTS FOUND ABOVE
            RecipeName = a.key

                        }).ToList(),
                }).ToList();

类似的东西:

                    let a = ViewRecipeSummary.GroupBy(x => x.RecipeName)
                        .Where(g => g.Any(x => x.IngredientName == recipeGroup.Key))
                        .Select(g => new ViewRecipe()
                            {
                                RecipeName = g.Key,
                                IngredientName = g.Select(x => x.IngredientName)
                            }) 

但是这会返回一个List,我需要将它分解为相同的结构。

以下是使用的类:

    public class GroupRecipe
    {
        public string RecipeName { get; set; }
        public List<GroupIngredient> Ingredients { get; set; }

        public GroupRecipe() { }
        public GroupRecipe(string _recipeName, List<GroupIngredient> _ingredients)
        {
            RecipeName = _recipeName;
            Ingredients = _ingredients;
        }
    }

   public class GroupIngredient
    {
        public string IngredientName { get; set; }
        public double UnitWeight { get; set; }
        public double TotalWeight { get; set; }

        public GroupIngredient() { }
        public GroupIngredient(string _IngredientName, double _UnitWeight, double _TotalWeight)
        {
            IngredientName = _IngredientName;
            UnitWeight = _UnitWeight;
            TotalWeight = _TotalWeight;
        }
    }
    public class ViewFullRecipe
    {
        public string RecipeName { get; set; }
        public List<GroupIngredient> RecipeIngredients { get; set; }
        public List<GroupRecipe> ViewGroupRecipes { get; set; }

        public ViewFullRecipe() { }
        public ViewFullRecipe(string _RecipeName, List<GroupIngredient> _RecipeIngredients, List<GroupRecipe> _ViewGroupRecipes)
        {
            RecipeName = _RecipeName;
            RecipeIngredients = _RecipeIngredients;
            ViewGroupRecipes = _ViewGroupRecipes;
        }
    }

2 个答案:

答案 0 :(得分:1)

如果我确实理解了您的问题,则以下代码应该有效。 正如其他人所说,我确实认为你的查询很复杂,而且不需要 我想你可能不想改变已经工作的东西, 我只是保持不变

var viewFullRecipeGrouping =
(
    from data in viewRecipeSummary
    group data by data.RecipeName
    into recipeGroup
    let fullIngredientGroups = recipeGroup.GroupBy(x => x.IngredientName)
    select new ViewFullRecipe()
        {
            RecipeName = recipeGroup.Key,
            RecipeIngredients =
                (
                    from ingredientGroup in fullIngredientGroups
                    select
                        new GroupIngredient
                            {
                                IngredientName = ingredientGroup.Key,
                                UnitWeight = ingredientGroup.Average(r => r.UnitWeight),
                                TotalWeight = ingredientGroup.Sum(r => r.TotalWeight)
                            }
                ).ToList(),

            ViewGroupRecipes =
                (
                    from recipeName in
                        viewRecipeSummary.GroupBy(x => x.IngredientName)
                                            .Where(g => fullIngredientGroups.Any(f => f.Key == g.Key))
                                            .SelectMany(g => g.Select(i => i.RecipeName))
                                            .Distinct()
                    select new GroupRecipe()
                        {
                            RecipeName = recipeName,
                            Ingredients =
                                viewRecipeSummary.Where(v => v.RecipeName == recipeName)
                                                    .GroupBy(i => i.IngredientName)
                                                    .Select(
                                                        g => new GroupIngredient
                                                            {
                                                                IngredientName = g.Key,
                                                                UnitWeight = g.Sum(i => i.UnitWeight),
                                                                TotalWeight = g.Average(i => i.TotalWeight)
                                                            }).ToList()
                        }
                ).ToList()
        }).ToList();

答案 1 :(得分:0)

我假设您的食谱组定义如下:

public class Recipe
{
    public string RecipeName { get; set; }
    public string IngredientName { get; set; }

    public Recipe() { }
    public Recipe(string _recipeName, string _IngredientName)
    {
        RecipeName = _recipeName;
        IngredientName = _IngredientName;
    }
}

public class RecipeGroup
{
    public string RecipeName{get;set;}
    public List<Recipe> Recipe{get;set;}
}

public class RecipeGroupDictionary
{
    private Dictionary<string, List<Recipe>> data;
    public RecipeGroupDictionary()
    {
        data = new Dictionary<string, List<Recipe>>();
    }
    public bool add(Recipe vr)
    {
        this[vr.RecipeName].Add(vr);
        return true;
    }
    public List<Recipe> this[string key]
    {
        get
        {
            if (!data.ContainsKey(key))
                data[key] = new List<Recipe>();
            return data[key];
        }
        set
        {
            data[key] = value;
        }
    }
    public ICollection<string> Keys
    {
        get
        {
            return data.Keys;
        }
    }
    public List<RecipeGroup> getRecipeGroup()
    {
        var result = new List<RecipeGroup>();
        foreach (var key in data.Keys)
        {
            result.Add(new RecipeGroup { RecipeName = key, Recipe = data[key] });
        }
        return result;
    }
}

class Program
{
    static void Main(string[] args)
    {
        var arr = new List<Recipe>();
        var recipeGroup = new RecipeGroupDictionary();
        arr.Add(new Recipe{ RecipeName="1", IngredientName="A"});
        arr.Add(new Recipe{ RecipeName="1", IngredientName="B"});
        arr.Add(new Recipe{ RecipeName="1", IngredientName="C"});
        arr.Add(new Recipe { RecipeName = "2", IngredientName = "B" });
        arr.Add(new Recipe { RecipeName = "2", IngredientName = "C" });
        arr.Add(new Recipe { RecipeName = "3", IngredientName = "A" });
        arr.Add(new Recipe { RecipeName = "3", IngredientName = "X" });
        arr.Add(new Recipe { RecipeName = "3", IngredientName = "Y" });

        var rnset = from row in arr
                    where row.IngredientName == "A"
                    select row.RecipeName;
        var result = (from row in arr
                      where rnset.Contains(row.RecipeName) && recipeGroup.add(row) //Won't be executed if the first condition is false.
                      select row ).ToArray(); //To array is List<Recipe>, if you don't want recipe group you can remove all the recipe dictionary related.
        foreach (var key in recipeGroup.Keys)
        {
            foreach(var recipe in recipeGroup[key])
                Console.WriteLine("RN:{0}, IA:{1}", recipe.RecipeName, recipe.IngredientName);
        }                      
    }
}