当您有一个复杂的对象结构时,如何将几个嵌套循环转换为lambda或linq
本文关键字:几个 嵌套循环 转换 linq lambda 复杂 有一个 对象 结构 | 更新日期: 2023-09-27 18:05:07
在尝试将多个嵌套循环转换为lambda或linq表达式时,我遇到了麻烦。我想我很难理解在使用。all或。contains方法时如何正确访问属性。无论如何,帮助是非常感激的。(我已经读了一些关于这个主题的其他帖子,但我仍然在努力使它工作。)
下面是这些类的样子:
public class RecipeSearch
{
public List<Recipe> Recipe { get; set; }
public List<Meal> MealSettings { get; set; }
public List<Ingredient> MainIngredient { get; set; }
}
public class Meal
{
public int Id { get; set; }
public bool Value { get; set; }
public string DisplayName { get; set; }
}
public class MainIngredient
{
public int Id { get; set; }
public bool Value { get; set; }
public string DisplayName { get; set; }
}
下面是嵌套循环:
IEnumerable<Recipe> recipeList = dbContext.Recipes
.OrderBy(r => r.name)
.Where(r => r.name.Contains(name) || string.IsNullOrEmpty(name))
.ToList();
//Model object is of type RecipeSearch
IEnumerable<Meal> selectedMeals = model.MealSettings.Where(x => x.Value == true);
IEnumerable<MainIngredient> selectedIngredients = model.MainIngredient.Where(x => x.Value == true);
foreach (var selected in recipeList) //loop through the master list
{
foreach (var item in selectedMeals) //loop through selected meal categories
{
if (selected.mealCategoryId == item.Id) //passed the meal category check (i.e. it exists)
{
foreach (var ingredient in selectedIngredients) // selected master ingredients
{
if (selected.Ingredients.Any(x => x.SubCategory.mainCategoryid == ingredient.Id))
{
recipe.Recipe.Add(selected);
break;
}
}
}
}
}
我想应该注意到循环完全按照预期工作。我只是觉得lambda/linq更容易读懂。
编辑:以下是其他对象:
public partial class Recipe
{
public Recipe()
{
Directions = new HashSet<Direction>();
Images = new HashSet<Image>();
Ingredients = new HashSet<Ingredient>();
Nutritions = new HashSet<Nutrition>();
Ratings = new HashSet<Rating>();
}
public int recipeId { get; set; }
//Removed other properties that are not relevant
public virtual ICollection<Ingredient> Ingredients { get; set; }
public virtual MealCategory MealCategory { get; set; }
public virtual RecipeStatus RecipeStatus { get; set; }
}
public partial class Ingredient
{
public int ingredientId { get; set; }
public int? recipeId { get; set; }
public int? subCategoryId { get; set; }
public int measurementId { get; set; }
public int amount { get; set; }
public virtual Recipe Recipe { get; set; }
public virtual SubCategory SubCategory { get; set; }
public virtual Measurement Measurement { get; set; }
}
public partial class SubCategory
{
public SubCategory()
{
Ingredients = new HashSet<Ingredient>();
}
public int subCategoryId { get; set; }
[Required]
[StringLength(255)]
public string name { get; set; }
public int? mainCategoryid { get; set; }
public virtual ICollection<Ingredient> Ingredients { get; set; }
public virtual Maincategory Maincategory { get; set; }
}
这样行吗?
var query = from selected in receipeList
join item in selectedMeals on selected.MealCategoryId equals item.Id
where selected.Ingredients.Select(x => x.SubCategory.mainCategoryid.Value)
.Intersect(selectedIngredients.Select(s => s.Id)).Count() > 0
select selected;
foreach(var sel in query)
recipe.Recipe.Add(sel);
我看不出你是从哪里得到recipe.Recipe
的。
基本上是为了帮助你把它转换成linq并根据你的需要进行调整:
:
foreach (var selected in recipeList) //loop through the master list
{
foreach (var item in selectedMeals) //loop through selected meal categories
{
if (selected.mealCategoryId == item.Id) //passed the meal category check (i.e. it exists)
{
}
}
}
转换成如下连接:
from selected in receipeList
join item in selectedMeals on selected.MealCategoryId equals item.Id
同样,这些行:
if (selected.Ingredients.Any(x => x.SubCategory.mainCategoryid == ingredient.Id))
{
recipe.Recipe.Add(selected);
break;
}
可译为:
where selected.Ingredients.Select(x => x.SubCategory.mainCategoryid.Value)
.Intersect(selectedIngredients.Select(s => s.Id)).Count() > 0
select selected;
//and then
foreach(var sel in query)
recipe.Recipe.Add(sel);
注意以下部分,
IEnumerable<Recipe> recipeList = dbContext.Recipes
.OrderBy(r => r.name)
.Where(r => r.name.Contains(name) || string.IsNullOrEmpty(name))
.ToList();
这里有2种气味:首先,您应该交换or条件来检查String。首先是IsNullOrEmpty,然后其次,将where放在order前面,以减少需要订购的项目。
IEnumerable<Recipe> recipeList = dbContext.Recipes
.Where(r => string.IsNullOrEmpty(name) || r.name.Contains(name))
.OrderBy(r => r.name)
.ToList();
根据ItemCount的不同,这可能会给你一些"boost"