C# 如何简化LINQ查询,该查询在字符串中搜索关键字并按相关性排序?

C# 如何简化LINQ查询,该查询在字符串中搜索关键字并按相关性排序?,c#,linq,linq-to-objects,C#,Linq,Linq To Objects,假设我有一些MyObjects,它们每个都有Description属性。我有一个关键字列表,我想用它在MyObject列表中搜索。我想按它们的描述包含的关键字数降序排列 示例输入(仅显示说明属性,注意初始顺序): 示例关键字: "Boo", "Foo" 样本输出(仅显示说明属性,注意最终顺序): “Bar”“Bar”不在结果中,因为它与0个关键字匹配 我目前正在使用一系列非常复杂的方法: return keywords.SelectMany( x => MyObjects.Whe

假设我有一些
MyObject
s,它们每个都有
Description
属性。我有一个关键字列表,我想用它在
MyObject
列表中搜索。我想按它们的
描述
包含的关键字数降序排列

示例输入(仅显示
说明
属性,注意初始顺序):

示例关键字:

"Boo", "Foo"
样本输出(仅显示
说明
属性,注意最终顺序):

“Bar”“Bar”不在结果中,因为它与0个关键字匹配

我目前正在使用一系列非常复杂的方法:

return keywords.SelectMany(
    x => MyObjects.Where(y => y.Description.ToLowerInvariant().Contains(x.ToLowerInvariant()))
    )
    .GroupBy(x => x)
    .OrderByDescending(x => x.Count())
    .Select(x => x.Key).ToList();
如您所见,我首先选择的是
关键字
。我认为,作为代码的读者,您应该首先看到对
MyObjects
进行一些转换。通常,当我写LINQ时,我试图在脑海中想象操作会是什么样子。看到关键词被转换,感觉很不直观。我也不喜欢
SelectMany
中的嵌套查询,因为它使查询语法看起来非常难看:

var query = from keyword in keywords
            from matchedObjects in (from obj in MyObjects where obj.Description.ToLowerInvariant().Contains(keyword.ToLowerInvariant()) select obj)
            group matchedObjects by matchedObjects into sameObjects
            orderby sameObjects.Count() descending
            select sameObjects.Key;
return query.ToList();
如何改进LINQ查询?理想情况下:

  • 没有嵌套查询
  • MyObjects.SomeLINQOperation…
    开头,而不是
    关键字
我希望有一种更简单/更直观的方法,因为这似乎是一件小事,但我也同意,如果提供解释,没有更简单的方法

results = myObjects.OrderByDescending(myObject => keywords.Where(keyword => myObject.Description.Contains(keyword)).Count());
给你所需要的

编辑:

不确定这算不算“更好”。

试试:

    var objects = new[]{
                    new MyObject{Description = "Foo Bar"},
                    new MyObject{Description = "Foo Boo"},
                    new MyObject{Description = "Foo Bee"},
                    new MyObject{Description = "Bar Bee"},
                    new MyObject{Description = "Boo Bee"},
                };
                var keywords = new[] { "Foo", "Bar" };
                var results = objects
                    .GroupBy(x => keywords.Where(
                                          keyword => x.Description.Contains(keyword) 
                                          ).Count()
                    )
                    .Where(x => x.Key > 0) // discard no matches
//                    .OrderByDescending(x => x.Count()) // order by mathing objects count
                    .OrderByDescending(x => x.Key)
//                   .ToDictionary(x => x.Key, x => x.ToArray())
                     .Select(x => new {Count = x.Key, Objects = x.ToArray()}).ToList(); // or create anonymous type
                    ;

它用匹配计数来计数对象,不丢弃匹配项,并将最多匹配放在顶部

你认为什么是“改进”?更快的代码?Shorder代码?更少的内存消耗代码?正因为如此,这个问题是基于quiute opnion的,并且吸引了许多不同的答案,努力寻找不同的测量方法。除了这个关于工作代码的问题外,你应该去@HimBromBeere看看这两个要点?这就是我想要的,与速度无关。我不认为这是基于观点的,因为这两点非常客观。错过了过滤没有关键字的MyObject的部分。编辑了我的答案。这满足了我的一个愿望+1:)将接受,如果没有其他人发布更好的东西或解释为什么两者不能同时满足。Tbh我不需要匹配多少关键字,所以可能
SelectMany(x=>x)
会起作用,对吗?@Sweeper是的,应该可以
results = myObjects.OrderByDescending(myObject => keywords.Where(keyword => myObject.Description.Contains(keyword)).Count());
var temp = myObjects.Where(myObject => keywords.Any(keyword => myObject.Description.Contains(keyword)))
            .OrderByDescending(myObject => keywords.Where(keyword => myObject.Description.Contains(keyword)).Count());
    var objects = new[]{
                    new MyObject{Description = "Foo Bar"},
                    new MyObject{Description = "Foo Boo"},
                    new MyObject{Description = "Foo Bee"},
                    new MyObject{Description = "Bar Bee"},
                    new MyObject{Description = "Boo Bee"},
                };
                var keywords = new[] { "Foo", "Bar" };
                var results = objects
                    .GroupBy(x => keywords.Where(
                                          keyword => x.Description.Contains(keyword) 
                                          ).Count()
                    )
                    .Where(x => x.Key > 0) // discard no matches
//                    .OrderByDescending(x => x.Count()) // order by mathing objects count
                    .OrderByDescending(x => x.Key)
//                   .ToDictionary(x => x.Key, x => x.ToArray())
                     .Select(x => new {Count = x.Key, Objects = x.ToArray()}).ToList(); // or create anonymous type
                    ;