简体   繁体   中英

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 more 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).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM