【问题标题】:Linq query with All rule in array具有数组中所有规则的 Linq 查询
【发布时间】:2015-07-12 15:10:06
【问题描述】:

我有一个图像列表,我想使用 BOTH 规则搜索多个关键字

例如,如果我搜索“dancing child”,我想显示包含关键字 dance 和 child 的项目列表

我实现了一个类似这样的查询:

List<string> target_keywords = //an array contains Keywords to Lookup 
var RuleAny_results = (from imageItem in images                     
                       select new{ imageItem,
                             Rank =target_keywords.Any(x => imageItem.Title != null && imageItem.Title.ToLower().Contains(x)) ? 5 :
                                   target_keywords.Any(x => imageItem.Name != null && imageItem.Name.ToLower().Contains(x)) ? 4 :                                  
                                0
                         }).OrderByDescending(i => i.Rank);
//exclude results with no match (ie rank=0 ) and get a Distinct set  of items
_searchResult = (from item in RuleAny_results
             where item.Rank != 0
             select item.imageItem).Distinct().ToList();

但这将返回包含target_keywords 中任何项目的结果,例如如果我在上面的代码中搜索“跳舞的孩子”,则返回带有任何关键字 dance 或 child 的项目列表。但我只想要包含跳舞和儿童关键字的列表

那么如何转换查询以获取包含 BOTH 关键字的所有记录?

【问题讨论】:

    标签: c# linq


    【解决方案1】:

    System.Linq.Enumerable::All 就是你想要的。

    using System.Linq;
    using System.Collections.Generic;
    
    struct ImageItem {
        public string Title { get; set; }
        public string Name { get; set; }
    }
    
    bool Contains(string toSearch, string x) {
        return toSearch != null && toSearch.ToLower().Contains(x);
    }
    
    IEnumerable<ImageItem> FilterItems(IEnumerable<string> targetKeywords, IEnumerable<ImageItem> items) {
        return items.Where(item => targetKeywords.All(x => Contains(item.Name, x) || Contains(item.Title, x)));
    
    }
    

    【讨论】:

    • 我尝试了所有但问题是如果标题包含“跳舞”并且名称包含“孩子”然后“跳舞的孩子”关键字返回 0 结果与所有
    • 你希望它返回什么?!
    • 我想返回包含两个关键字的项目列表 [关键字可以在 Title 或 Name 属性中] 就像 Title 包含“dancing”并且 Name 包含“child”然后我想返回该项目作为关键字“跳舞的孩子”的结果
    • 那么排名的意义何在?为什么你不能像这样使用 Where ? images.Where(imageItem =&gt; targetKeywords.All(x =&gt; Contains(item.Title, x) || Contains(item.Name, x))
    • 它很有帮助,但我最终得到了一个解决方案,即为每个关键字查找包含搜索列表,并提取所有的交集作为结果列表
    【解决方案2】:

    试试这个:--

    您只需将语法中的 Any 关键字替换为 All
    以及两个字段中所有关键字的另一个排名条件

    target_keywords.Any( 替换为target_keywords.All(

    List<string> target_keywords = //an array contains Keywords to Lookup 
    var RuleAny_results = (from imageItem in images                     
                           select new{ imageItem,
                                 Rank =target_keywords.Any(x => imageItem.Title != null && imageItem.Title.ToLower().Contains(x)) ? 5 :
                                       target_keywords.All(x => imageItem.Name != null && imageItem.Name.ToLower().Contains(x)) ? 4 :   
                                       target_keywords.All(x => (imageItem.Name != null && imageItem.Name.ToLower().Contains(x)) || imageItem.Title != null && imageItem.Title.ToLower().Contains(x)) ? 3 :                                
                                    0
                             }).OrderByDescending(i => i.Rank);
    //exclude results with no match (ie rank=0 ) and get a Distinct set  of items
    _searchResult = (from item in RuleAny_results
                 where item.Rank != 0
                 select item.imageItem).Distinct().ToList();
    

    【讨论】:

    • 我看到您只将Any 更改为All 之一,这是故意的吗?这将允许通过标题为“Dancing”和空名称的 ImageItem,这不是 OP 想要的。当然,您可以将另一个 Any 更改为 All,但这不允许以“Dancing”为标题、“Girl”为 Name 的内容,这也不是 op 想要的。
    • 它仍然允许通过标题为“Dancing”且名称为空的项目
    【解决方案3】:
    class ImageDemo
        {
            public string Title { get; set; }
            public string Name { get; set; }
        }
    
        static void TestCode()
        {
            List<string> target_keywords = new List<string>(){"dancing","child"};
            List<ImageDemo> images = new List<ImageDemo>()
            {  
                new ImageDemo{Title = "dancing"}  ,
                 new ImageDemo{Name = "child"}  ,
                 new ImageDemo{Title = "child", Name="dancing"}  ,
                 new ImageDemo{Title = "dancing", Name="child"}  ,
                 new ImageDemo{Name="dancing child"} ,
                 new ImageDemo{Title="dancing child"} 
            };
            var searchFuncs = target_keywords.Select(x =>
            {
                Func<ImageDemo, bool> func = (img) =>
                {
                    return (img.Title ?? string.Empty).Contains(x) || (img.Name ?? string.Empty).Contains(x);
                };
                return func;
            });
            IEnumerable<ImageDemo> result = images;
            foreach (var func in searchFuncs)
            {
                result = result.Where(x => func(x));
            }
            foreach (var img in result)
            {
                Console.WriteLine(string.Format("Title:{0}  Name:{1}", img.Title, img.Name));
            }
        }
    

    现在是你想要的正确代码吗?

    【讨论】:

    • 这个答案并不能解决同时搜索图片名称和标题的问题。
    • 这仍然不能真正解决问题。如果标题和名称都存在,那么您只是在标题中搜索,这对您拥有 new ImageDemo { Name = "Dancing", Title = "Child"} 的 OP 示例没有帮助
    • 这意味着你需要标题和名称中的所有关键字?
    猜你喜欢
    • 1970-01-01
    • 2022-06-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多