C# 林克,第三个嵌套的孩子';s的属性值是否等于某个值?

C# 林克,第三个嵌套的孩子';s的属性值是否等于某个值?,c#,linq,collections,C#,Linq,Collections,我在获取LINQ时遇到了一些问题,如果要返回任何结果,我有几个类似的类: public class RestaurantMenu { public List<MenuItem> MenuItems { get; set; } } public class MenuItem { public decimal Price { get; set; } public List<FoodItem> FoodItems { get; set; } } pu

我在获取LINQ时遇到了一些问题,如果要返回任何结果,我有几个类似的类:

public class RestaurantMenu
{
    public List<MenuItem> MenuItems { get; set; }
}

public class MenuItem
{
    public decimal Price { get; set; }
    public List<FoodItem> FoodItems { get; set; }
}

public class FoodItem
{
    public string Label { get; set; }
}
我试着在下面的表达式中链接:

IQueryable<RestaurantMenu> query = allRestaurantMenus.AsQueryable();

        foreach (string foodItem in labelOfFoodItemsDesired)
        {
            query = query.Where(x => x.MenuItems.Any(y => y.FoodItems.Select(z => z.Label).Contains(foodItem)));
        }

        List<RestaurantMenu> matchingRestaurantMenus = query.ToList();
IQueryable query=allRestaurantMenus.AsQueryable();
foreach(需要LabelOffodItems中的字符串foodItem)
{
query=query.Where(x=>x.MenuItems.Any(y=>y.FoodItems.Select(z=>z.Label).Contains(foodItem));
}
List matchingrestarantmenus=query.ToList();
但它总是不返回任何结果,即使通过调试我确信存在匹配。我将如何编写此查询

allRestaurantMenus.Where(m => 
    m.MenuItems.Any(mi => 
        !labelOfFoodsDesired.Except(mi.FoodItems.Select(fi => fi.Label)).Any()))
工作原理:我们正在筛选至少有一个菜单项和您传递的所有标签的菜单。与

我们生产所需标签和所有食品标签之间的差异。如果食品标签中存在所有所需标签,则集合将为空

更新:若您应该检查任何菜单项(而不是单个菜单项),那个么查询将如下所示

allRestaurantMenus.Where(m => 
    !labelOfFoodsDesired.Except(
       m.MenuItems.SelectMany(mi => mi.FoodItems.Select(fi => fi.Label))).Any())
工作原理:方法同上,但您应该检查所有菜单项的所有标签。这样就可以将菜单项集合展平为所有标签的集合。然后,如上所述,您可以在所需标签和所有菜单项的所有标签之间构建集合差异。若设置为空,则菜单满足您的条件

测试:给定以下菜单

List<RestaurantMenu> allRestaurantMenus = new List<RestaurantMenu> {
    new RestaurantMenu {
            MenuItems = new List<MenuItem> {
                new MenuItem {
                    FoodItems = new List<FoodItem> {
                        new FoodItem { Label = "Chocolate" },
                        new FoodItem { Label = "Water" }
                    }
                },
                new MenuItem {
                    FoodItems = new List<FoodItem> {
                        new FoodItem { Label = "Egg" },
                        new FoodItem { Label = "Ketchup" }
                    }
                }
            }
    },
    new RestaurantMenu {
        MenuItems = new List<MenuItem> {
                new MenuItem {
                    FoodItems = new List<FoodItem> {
                        new FoodItem { Label = "Water" }
                    }
                },
                new MenuItem {
                    FoodItems = new List<FoodItem> {
                        new FoodItem { Label = "Banana" },
                        new FoodItem { Label = "Peach" }
                    }
                }
           }
      }
 };
然后,它将在所需标签和此展平结果之间建立集差:

{ "Banana" }
{ }

因此,第二个结果是空的(所有所需的标签都存在于菜单中),只有第二个菜单匹配。

我认为类似的方法可以工作。我确信您可以删除foreach的
foreach
,使其成为单个linq查询

foreach (var restaurant in allRestaurantMenus)
{
    var restaurantFoodItems = restaurant.MenuItems.SelectMany(m => m.FoodItems);
    bool hasAllFoods = labelOfFoodsDesired.All(lf => restaurantFoodItems.Contains(lf));

    if (hasAllFoods)
        yield return restaurant;
}

您可以将
中的
组合使用,除了
-
任何

var allMatches = allRestaurantMenus
    .Where(rm => !labelOfFoodsDesired
        .Except(rm.MenuItems.SelectMany(f => f.FoodItems.Select(fi => fi.Label)))
        .Any());
labelofoodsdeired。除了(所有菜单食品标签)。如果一个或多个所需标签不可用,Any()
将返回
true
反转条件,以便检查所有食物的可用位置。它是有效的,因为
Except
在内部使用集合

allRestaurantMenus.Where(x => labelOfFoodsDesired.All(b => x.MenuItems.SelectMany(y => y.FoodItems.Select(a => a.Label)).Contains(b)));

其工作原理是将该列表中的所有食物放入一个列表,然后对所有需要的食物进行检查。

我认为链接调用的错误在于重新分配了查询变量。因此,您的查询(包含所有RestaurantMenus)被设置为null或空列表。如果我理解正确,则不是这样。由于可查询对象的延迟执行,我可以像上面那样构造查询,直到调用list,它才真正执行。这与执行类似query.Where(x=>Id==2)、Where(x=>x.Id==3)、Where(x=>x.Id==4)的操作没有什么区别。在执行之前,它将它们组合成一个查询query.Where(x=>x.Id==2&&x.Id==3&&x.Id==4)。并不是说这会返回任何结果,因为这是不可能的,只是举个例子。这不是我所需要的,如果我解释得不好,我很抱歉。菜单需要包含所需的所有食物,但不必是单个菜单项,可以是单个菜单项,也可以是多个菜单项,只要它们都在一家餐厅。@DOTang没问题,已更新查询。在这种情况下,您应该将所有菜单项展平到标签集合中,并检查展平的集合中是否存在所有所需的标签,最后一个集合仍然返回零结果。我正在更新我的问题以包含样本数据。@DOTang刚用样本数据验证过(更新了我的答案)-工作正常
{ "Banana" }
{ }
foreach (var restaurant in allRestaurantMenus)
{
    var restaurantFoodItems = restaurant.MenuItems.SelectMany(m => m.FoodItems);
    bool hasAllFoods = labelOfFoodsDesired.All(lf => restaurantFoodItems.Contains(lf));

    if (hasAllFoods)
        yield return restaurant;
}
var allMatches = allRestaurantMenus
    .Where(rm => !labelOfFoodsDesired
        .Except(rm.MenuItems.SelectMany(f => f.FoodItems.Select(fi => fi.Label)))
        .Any());
allRestaurantMenus.Where(x => labelOfFoodsDesired.All(b => x.MenuItems.SelectMany(y => y.FoodItems.Select(a => a.Label)).Contains(b)));