检查集合是否包含来自具有延迟执行的其他集合的所有值

时间:2017-02-25 00:34:46

标签: c# linq

考虑以下课程:

public class Recipe
{
    public string Id { get; set; }
    public ICollection<RecipeFacet> RecipeFacets { get; set; }
}

public class RecipeFacet
{
    public string Id { get; set; }
    public Facet Facet { get; set; }
    public string RecipeId { get; set; }
}

public class Facet
{
    public string Name { get; set; }
}

我需要改进现有的查询。我在考虑使用Linq的延迟执行。如何编写仅返回Recipes的Linq查询,其中包含我在Facets列表中指定的所有Tuples

这是循环遍历Recipes及其Facets的原始代码。如果我的初始results查询有很多Recipes

,它会很有效
IQueryable<Recipe> result; //assume we have data here

string query = "Cuisine:American+Recipe-Type:dinners";
IEnumerable<Tuple<string, string>> taxFacets = query
            .Split(' ')
            .Select(tf => tf.Split(':'))
            .Select(tf => new Tuple<string, string>(tf[0], tf[1]))
            .Distinct();

var recipeFacetCollection = result.Select(r => r.RecipeFacets).ToList();
var matchedRecipesIds = new List<string>();

var recIds = result.Select(r => r.Id).ToList();

// initially, include all recipes
matchedRecipesIds.AddRange(recIds);

// loop through each recipe's facet collection
foreach (var col in recipeFacetCollection)
{
    // loop through the tax facets from the query
    foreach (var tf in taxFacets)
    {
        var exists = col.Any(f => f.Facet.Name.Equals(tf.Item2, StringComparison.OrdinalIgnoreCase));
        // remove any recipe that is missing a facet
        if (!exists)
        {
            matchedRecipesIds.Remove(col.First().RecipeId);
        }
    }
}

result = result.Where(r => matchedRecipesIds.Contains(r.Id));

如何使用延迟执行获得一个漂亮的Linq查询?

UPDATE ::

将我的元组转换为列表允许我这样做。但是这个查询并没有返回我的任何记录。

这是我的标准:

Recipes,其集合RecipeFacts,其中包含Facets,其名称=&#34;美国&#34; AND Name =&#34;晚餐&#34;。

var listFacets = new List<string>()
{
    "American",
    "dinners"
};

 result = result
      .Where(r => r.RecipeFacets
      .All(f => !listFacets.Any(t => t.Equals(f.Facet.Name, StringComparison.OrdinalIgnoreCase))));

4 个答案:

答案 0 :(得分:1)

您的查询逻辑会选择其面板不在listFacets中的所有食谱。 @ Hung的逻辑更接近,但选择了listFacets中所有面的

的食谱

我认为您要选择包含所有listFacets的所有食谱。

简化使用字符串列表的示例:

        var listFacets = new[] { "a", "d" };
        var recipes = new[] { new[] { "a" },
                              new[] { "a", "d" },
                              new[] { "a", "d", "e" },
                              new[] { "x" }
        };

        // correct query, returns 2 results ad and ade
        var result = recipes.Where(r => listFacets.All(f => r.Any(rf => rf == f)));
        // original incorrect query, returns x
        var result2 = recipes.Where(r => r.All(f => !listFacets.Any(rf => rf == f)));

答案 1 :(得分:0)

我不太确定你的代码块是否很长但是我可以提出

result = result.Where(r => r.RecipeFacets.All(f => taxFacets.Any(t => t.Item1.Equals(f.Facet.Name))));

让我知道它是否有帮助

答案 2 :(得分:0)

从listFacets集合中检查中删除子句中的感叹号。

result = result.Where(r => r.RecipeFacets.All(f => listFacets.Any(t => t.Equals(f.Facet.Name, StringComparison

答案 3 :(得分:0)

我是从@Rimmp的帮助中得到的。

WHERE - 过滤器
全部 - 要求listFacets的所有值 ANY - 位于Facets的任意内容中。

result = result
     .Where(x => listFacets
     .All(lf => x.RecipeFacets
     .Any(f => f.Facet.Slug.Equals(lf, StringComparison.OrdinalIgnoreCase))));