Can this linq query be more efficient?
I'm new to linq and making myself use it more and more to get familiar. I just replaced a bunch of ugly dictionary-based grouping and counting code with the following linq statement:
using System;
using System.Linq;
namespace WindowsForms_TestBench
{
static class Program
{
[STAThread]
static void Main()
{
string[] numbers = new string[] { "1", "2", "1", "1", "3", "2", "1" };
var groupedNumbers =
from number in numbers
group number by number into grouped
select new { Number = grouped.Key, Count = grouped.Count() };
foreach (var groupedNumber in groupedNumbers)
Console.WriteLine("{0}({1})", groupedNumber.Number, groupedNumber.Count);
}
}
}
Pretty straightforward what's it's doing but I'm just curious if anyone spots a m开发者_如何学JAVAore efficient or, in your opinion, "better" way to accomplish the same output.
Other than arguing about syntax and whether to use the function style verses query syntax (you used the query syntax), there isn't much more to it.
You've grouped and counted in a standard way and (unless you dig way deeper than most devs), you're unlikely to find a "better" way.
Just for info, the functional syntax would be:
foreach (var group in numbers.GroupBy(number => number))
{
Console.WriteLine("{0}({1})", group.Key, group.Count());
}
No - that looks pretty efficient, compact and readable to me.
If you cared about speed then you could add AsParallel()
- but for small data sets that would make performance worse!
- and using Parallel with groupby possibly adds requirements for lots more memory
No, that's pretty much the most reasonable way to do it. Internally, it's making a hashtable to store the counts, so the performance is probably similar to your old approach.
That query is perfectly fine for what you're doing (and probably the most efficient LINQ statement to get the information you want).
Keep in mind that you are using query syntax so things will look a little verbose but it is no less efficient.
The equivalent lambda syntax would look something like this:
var results = numbers.GroupBy(n => n)
.Select(g => new { g.Key, Count = g.Count() });
Which looks a little more compact but does the exact same thing.
I would convert the code below to Lambda Syntax
var groupedNumbers =
from number in numbers
group number by number into grouped
select new { Number = grouped.Key, Count = grouped.Count() };
In response to @Matt Greer
Lambda Syntax:
var groupedNumbers = number.GroupBy(x=> x.number).Select(x=> new
{
Number = x.Key,
Count = x.Count()
});
This may not be a correct translation, but demonstrates the point.
To push John Fisher's functional example a bit further, you could go with:
static void Main()
{
string[] numbers = new string[] { "1", "2", "1", "1", "3", "2", "1" };
(from number in numbers
group number by number into grouped
select new { Number = grouped.Key, Count = grouped.Count() }
).ToList().ForEach(
group => Console.WriteLine("{0}({1})", group.Number, group.Count)
);
}
However, you have to use the ToList()
method as IEnumerable
does not provide a ForEach
interface (see "LINQ equivalent of foreach for IEnumerable" for a discussion on the subject).
精彩评论