I've got the following code to extract keywords from a string:
var results = text.Split(new char[]{' ',',','.','!','?','_',':',';','/','(',')','\n','\r','-','*','"','/','\\','$','%','+','-','='}) // default split by whitespace
.GroupBy(str => str) // group words by the value
.Select(g => new
{
str = g.Key, // the value开发者_JAVA技巧
count = g.Count() // the count of that value
});
Now I need to add OrderByDescending
to it, but not sure where to place it.
.GroupBy(str => str).OrderByDescending(count => count)
yielded incorrect results. How to make it right?
You can add it after the select.
.Select(...whatever...).OrderByDescending(item => item.count);
You're misunderstanding is due to the fact that you give the variable in the lambda the same name as a property on the anonymous type. The OrderByDescending(count => count)
sorts on the whole object. What you want is to sort on the count-property, so you should use OrderByDescending(x => x.count)
.
Use it after the GroupBy and call g.Count()
the same way you did in your Select
statement:
.GroupBy(str => str)
.OrderByDescending(g => g.Count())
.Select(g => new ...) // rest of your code here
EDIT: I actually prefer Anthony's answer to my own and was about to modify mine but by then he had posted his response. It's a very minor concern and is a premature optimization, but my posted approach will be slightly slower when dealing with large collections since Count()
is being executed twice, whereas Anthony's approach is sorting on the already computed Count()
made in the Select
statement. Just something to keep in mind when constructing clean LINQ queries.
As an aside, in query syntax we can get around this by storing the count in a let
(sure, this is possible in fluent syntax but feels more natural in query syntax) which would provide good performance. Something like this:
var query = from g in text.Split(...).GroupBy(str => str)
let count = g.Count()
orderby count descending
select new { str = g.Key, Count = count };
精彩评论