C# 如何使用let在LINQ查询中定义一组新数据?
我有一个代表食谱所有成分的类C# 如何使用let在LINQ查询中定义一组新数据?,c#,linq,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 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的列表,如下所示:
RecipeName IngredientName
1 A
1 B
1 C
2 D
2 E
3 A
3 Z
RecipeName IngredientName
1 A
1 B
1 C
3 A
3 Z
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);
}
}
}
我有一个查找INGRIDENT(recipeGroup.Key)的现有查询,现在需要执行以下操作:
1-找到所有含有该成分的食谱
2-从我的数据中返回这些配方的所有行
然后我需要在我的查询中使用它(所以它需要使用LET或其他东西)
假设我正在寻找所有共享成分A的配方,我希望我的LET的最终结果(基于我上面显示的数据)与此完全相同:
RecipeName IngredientName
1 A
1 B
1 C
2 D
2 E
3 A
3 Z
RecipeName IngredientName
1 A
1 B
1 C
3 A
3 Z
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);
}
}
}
因此,对于任何含有成分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)
})
但这会返回一个列表,我需要返回分解为相同结构的列表
以下是使用的类:
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;
}
}
公共类GroupRecipe
{
公共字符串RecipeName{get;set;}
公共列表成分{get;set;}
公共组配方(){}
公共组配方(字符串\u recipeName,列表\u成分)
{
RecipeName=_RecipeName;
配料=_配料;
}
}
公共类组元素
{
公共字符串IngCreditName{get;set;}
公共双单位重量{get;set;}
公共双总权重{get;set;}
公共组元素(){}
PublicGroupComponent(字符串\u IngCreditName、双重单位重量、双重总重量)
{
IngredientName=\u IngredientName;
单位重量=_单位重量;
总重量=_总重量;
}
}
公共类ViewFullRecipe
{
公共字符串RecipeName{get;set;}
公共列表RecipeIngElements{get;set;}
公共列表ViewGroupRecipes{get;set;}
public ViewFullRecipe(){}
公共ViewFullRecipe(字符串_RecipeName、列表_RecipeInElements、列表_ViewGroupRecipes)
{
RecipeName=_RecipeName;
接收要素=_接收要素;
ViewGroupRecipes=\u ViewGroupRecipes;
}
}
我假设您的配方组定义如下:
RecipeName IngredientName
1 A
1 B
1 C
2 D
2 E
3 A
3 Z
RecipeName IngredientName
1 A
1 B
1 C
3 A
3 Z
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);
}
}
}
公共类配方
{
公共字符串RecipeName{get;set;}
公共字符串IngCreditName{get;set;}
公共配方(){}
公共配方(字符串_recipeName,字符串_IngCreditName)
{
RecipeName=_RecipeName;
IngredientName=\u IngredientName;
}
}
公共类RecipeGroup
{
公共字符串RecipeName{get;set;}
公共列表配方{get;set;}
}
公共类RecipeGroupDictionary
{
专用字典数据;
公共RecipeGroupDictionary()
{
数据=新字典();
}
公共bool添加(配方vr)
{
此[vr.RecipeName].Add(vr);
返回true;
}
公共列表此[字符串键]
{
得到
{
如果(!data.ContainsKey(键))
数据[键]=新列表();
返回数据[键];
}
设置
{
数据[键]=值;
}
}
公共ICollection密钥
{
得到
{
返回数据。键;
}
}
公共列表getRecipeGroup()
{
var result=新列表();
foreach(data.Keys中的var键)
{
Add(新的RecipeGroup{RecipeName=key,Recipe=data[key]});
}
返回结果;
}
}
班级计划
{
静态void Main(字符串[]参数)
{
var arr=新列表();
var recipeGroup=新的RecipeGroupDictionary();
arr.Add(新配方{RecipeName=“1”,IngreditName=“A”});
arr.Add(新配方{RecipeName=“1”,IngreditName=“B”});
arr.Add(新配方{RecipeName=“1”,IngreditName=“C”});
arr.Add(新配方{RecipeName=“2”,IngreditName=“B”});
arr.Add(新配方{RecipeName=“2”,IngreditName=“C”});
arr.Add(新配方{RecipeName=“3”,IngreditName=“A”});
arr.Add(新配方{RecipeName=“3”,IngreditName=“X”});
arr.Add(新配方{RecipeName=“3”,IngreditName=“Y”});
var rnset=来自arr中的行
其中row.IngredientName==“A”
选择row.RecipeName;
var结果=(来自arr中的行
其中,如果第一个条件为false,则不会执行rnset.Contains(row.RecipeName)和&recipeGroup.add(row)//命令。
选择row).ToArray();//To array is List,如果不需要配方组,可以删除所有与配方字典相关的内容。
foreach(往复组合键中的var键)
{
foreach(recipeGroup[key]中的var配方)
WriteLine(“RN:{0},IA:{1}”,recipe.RecipeName,recipe.IngreditName);
}
}
}
如果我理解了你的问题,下面的代码应该可以。
正如其他人所说,我确实认为您的查询很复杂,不需要这样做
我想你可能不想改变一直在运作的东西,
我只是保持不变
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();
我假设您正在使用ORM。您是如何生成ORM映射的?通常,ORM映射将为您提供关联(这是实际映射的类的属性)。请包括您的数据库模型类。如果您只想选择成分为“A”的配方,您的查询太复杂。我没有使用ORM,也没有数据库(比如说),它是一个列表格式的数据集合。至于它太复杂了,我不知道你的意思是什么,这是一个预先存在的查询,需要做很多事情,我只需要插入其中(