当前位置: 首页 > 知识库问答 >
问题:

C#如何将数组中的所有项与搜索项列表匹配

艾浩穰
2023-03-14

我有一门食谱课:

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”标签存在。

如何确保返回的是完全匹配的?

共有2个答案

毛成济
2023-03-14

尝试对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();
        }

工作原理:

  1. 遍历recipes数组,它是输入
  2. 使用逻辑&&
  3. 检查所有条件
  4. chefname是单个元素检查,对于其他元素,我们使用Linqany来遍历和匹配,如果存在单个匹配
  5. 当满足所有条件时,我们将元素添加到匹配
  6. 返回matches.distinction().toArray();在我看来不是必需的,因为我们不会多次添加相同的制作方法,您可以只返回匹配
  7. 您需要添加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();
        }

    }
卫兴邦
2023-03-14

我不确定在字符串中遍历成分的逻辑是什么,也许您也应该将它们列成一个列表。无论如何,您可以为每个菜谱创建一个菜谱搜索项数组,并返回所有的菜谱,其中所有用户输入的搜索项都包含这些菜谱搜索项。

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();
 类似资料:
  • 问题内容: 如何在SQL Server中搜索表的所有列? 问题答案: 如果您正在寻找完全的全场比赛。如果要查找子字符串匹配项,则必须进行很长的路要走:

  • 问题内容: 我需要在JavaScript中搜索数组。搜索将仅针对字符串的一部分进行匹配,因为该字符串将分配有其他数字。然后,我需要返回带有完整字符串的成功匹配的数组元素。 即 我需要搜索其中包含的数组元素,并且也需要在元素中提取其余文本(即)。 谢谢 问题答案: 在您的特定情况下,您可以使用一个无聊的旧柜台来做到这一点: 但是,如果您的数组是稀疏的,则可以通过适当设计的循环来更有效地执行此操作:

  • 我有一个C#平台上的winform项目。我有listview和textbox,如下图所示。我想根据用户输入的文本值对列表重新排序。 我在这里询问之前研究过,我通常会看到基于删除和重新添加所有单元到listview的解决方案。我不想这样做,因为我的listview有太多带图片的项目,所以删除和重新添加项目会导致listview工作缓慢。 我想要的是,当用户在文本框中输入字符时,以这些字符开头的项目,

  • 问题内容: 前几天,我接受了亚马逊的采访,他们问我一个问题,涉及以下问题。 给定2个整数数组,其中包含任意数量的正负元素,请查找出现在两个数组中的数字。 我能够非常轻松地解决此问题,因此它将具有计算复杂性,但是不幸的是,这还将具有空间复杂性。可以通过遍历每个数组中的所有元素而无需额外的内存来完成此操作,但这将是。 在我解释完该方法之后,面试官问我是否可以想到一种在计算上为O(n)但不会使用任何额外

  • 问题内容: 只会给出列表中第一个出现的项目。有没有整齐的技巧可以返回列表中的所有索引? 问题答案: 你可以使用列表理解:

  • 我在研究弹性搜索查询。我不能理解这个问题: 我读过这篇文章,但不清楚:http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-term-query.html 1-第二个“term”是什么? 2-boost的用法是什么? 3-如何使用一个或多个term进行查询: 名为“title”的字段必须包含: