我有一门食谱课:
public class Recipe
{
public string Id { get; set; }
public string RecipeTitle { get; set; }
public string ChefName { get; set; }
public List<string> HashTags { get; set; }
public string Ingredients { get; set; }
}
用户可以在搜索框中输入搜索词列表,我想返回匹配所有搜索词的食谱。以下是我到目前为止的代码:
public Recipe[] SearchRecipes(string[] searchTerms, Recipe[] recipes)
{
var matches = new List<Recipe>();
foreach (var recipe in recipes)
{
if (searchTerms.Contains(recipe.ChefName, StringComparer.OrdinalIgnoreCase))
{
matches.Add(recipe);
}
foreach (var tag in recipe.Hashtags)
{
if (searchTerms.Contains(tag, StringComparer.OrdinalIgnoreCase))
{
matches.Add(recipe);
}
}
foreach (var title in recipe.RecipeTitle)
{
if (searchTerms.Contains(title, StringComparer.OrdinalIgnoreCase))
{
matches.Add(recipe);
}
}
}
return matches.Distinct().ToArray();
}
但是,这将返回仅与一个或两个条件匹配的项。例如。如果用户搜索“Chef Jane”和“Donald”,它还会返回来自“Chef Callum”的东西,因为“Donald”标签存在。
如何确保返回的是完全匹配的?
我不确定在字符串中遍历成分的逻辑是什么,也许您也应该将它们列成一个列表。无论如何,您可以为每个菜谱创建一个菜谱搜索项数组,并返回所有的菜谱,其中所有用户输入的搜索项都包含这些菜谱搜索项。
public Recipe[] SearchRecipes(string[] searchTerms, Recipe[] recipes)
{
var matches = new List<Recipe>();
foreach (var recipe in recipes)
{
// Just flattening all the hash tags together with other recipe search terms
var recipeTerms = recipe.HashTags
.Concat(new string[]
{
recipe.RecipeTitle,
recipe.ChefName,
recipe.Ingredients
});
// Will include only the recipes where all search terms are matched in recipe terms
if (searchTerms.All(searchTerm =>
recipeTerms.Contains(searchTerm, StringComparer.OrdinalIgnoreCase))
{
matches.Add(recipe);
}
}
return matches.ToArray();
}
您也可以手动执行all
逻辑,但这种方式更简单。它来自system.linq
命名空间,您可以在这里查看它的文档。
完整的LINQ解决方案如下所示:
public Recipe[] SearchRecipes(string[] searchTerms, Recipe[] recipes)
=> recipes.Where(recipe =>
{
var recipeTerms = recipe.HashTags
.Concat(new string[]
{
recipe.RecipeTitle,
recipe.ChefName,
recipe.Ingredients
});
return searchTerms.All(searchTerm =>
recipeTerms.Contains(searchTerm, StringComparer.OrdinalIgnoreCase));
})
.ToArray();
尝试对SearchRecipes
方法进行以下修改:
public Recipe[] SearchRecipes(string[] searchTerms, Recipe[] recipes)
{
var matches = new List<Recipe>();
foreach (var recipe in recipes)
{
if (
searchTerms.Contains(recipe.ChefName, StringComparer.OrdinalIgnoreCase) &&
recipe.HashTags.Any(tag => searchTerms.Contains(tag, StringComparer.OrdinalIgnoreCase)) &&
recipe.RecipeTitle.Any(title => searchTerms.Contains(title, StringComparer.OrdinalIgnoreCase))
)
matches.Add(recipe);
}
return matches.Distinct().ToArray();
}
工作原理:
recipes
数组,它是输入逻辑&&
chefname
是单个元素检查,对于其他元素,我们使用Linqany
来遍历和匹配,如果存在单个匹配匹配
返回matches.distinction().toArray();
在我看来不是必需的,因为我们不会多次添加相同的制作方法,您可以只返回匹配
system.linq
命名空间,此代码才能正常工作编辑(如果Chefname可能不匹配但标题和标记匹配)
public class Match
{
public Recipe[] SearchRecipes(string[] searchTerms, Recipe[] recipes)
{
var matches = new List<Recipe>();
var isMatch = false;
foreach (var recipe in recipes)
{
var chefNameCheck = searchTerms.Contains(recipe.ChefName, StringComparer.OrdinalIgnoreCase);
var tagCheck = recipe.HashTags.Any(tag => searchTerms.Contains(tag, StringComparer.OrdinalIgnoreCase));
var titleCheck = recipe.RecipeTitle.Any(title => searchTerms.Contains(title, StringComparer.OrdinalIgnoreCase)) ;
if (chefNameCheck && tagCheck && titleCheck)
matches.Add(recipe);
else if (tagCheck && titleCheck)
matches.Add(recipe);
}
return matches.Distinct().ToArray();
}
}