假设我有一些MyObject
个,每个都有一个Description
属性。我有一个关键字列表,我想用它来搜索MyObject
列表。我想按照每个Description
包含的关键字数量按降序排序。
示例输入(仅显示Description
属性,请注意初始顺序):
"Foo Bar"
"Foo Boo"
"Bar Bar"
示例关键字:
"Boo", "Foo"
示例输出(仅显示Description
属性,请注意最终顺序):
"Foo Boo" (matches 2 keywords)
"Foo Bar" (matches 1 keyword)
“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();
如您所见,我首先选择keywords
。我认为作为代码的读者,您可能希望首先在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...
而不是keywords
开头。我希望有一种更容易/更直观的方式,因为这似乎是一件微不足道的事情,但我也会接受,如果提供解释,没有更简单的方法。
答案 0 :(得分:2)
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());
不确定这是否更好'。
答案 1 :(得分:1)
试试:
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
;
它按匹配计数对象进行分组,不丢弃匹配项并将最多匹配项放在顶部