John Ohara
John Ohara

Reputation: 2901

Refactor linq query and return a single after grouping

I have the following linq query:

            var q = Queryable.First(Queryable.Select(r.Find((Expression<Func<Application, bool>>)((Application x) =>
                 x.IsValid && x.CreatedOn < startDate && x.CreatedOn >= endDate))
                .GroupBy((Expression<Func<Application, int>>)((Application x) => (int)1))
                , (IGrouping<int, Application> g) => new
                {
                    AvgApplicationTime = (int)Math.Round(g.Average((Application i) => i.ApplicationTime)),
                    AvgDecisionTime = (int)Math.Round(g.Average((Application i) => i.DecisionTime)),
                    ApprovalRate = 100.0 * g.Count<Application>((Application i) => i.IsAccepted) / g.Count<Application>()
                }));

            return new ApplicationStats((int)q.AvgApplicationTime, (int)q.AvgDecisionTime, q.ApprovalRate);

I'm pretty sure the query can be simplified and have set out to do so.

My approach is always to try and understand a query I'm working with, rather than just hacking bits about and hoping it works.

In doing so, I like to break it down into parts before reassembling, which I've tried to do here:

            var q1 = r.Find(x => x.CreatedOn < startDate && x.CreatedOn >= endDate);

            var q2 = q1.Select(x => x.Applicant);

            var q3 = q2.GroupBy(x => 1, (g) => new ApplicationStats(1, 1, 0.75)); // I've omitted some bits for brevity

            // q4 = ??? // Needs to return a single Applicationstats()

Unfortunately, I haven't managed to figure out the final piece of the puzzle, despite using a combination of .Select(), .SelectMany(), .First().

I know the answer will prove simple but any help is appreciated.

Upvotes: 1

Views: 47

Answers (1)

John Ohara
John Ohara

Reputation: 2901

There are numerous issues with the new query.

bommelding was correct - the final bit of the puzzle was q4 = q3.First(),

However, this will not work without other changes to this statement:

var q3 = q2.GroupBy(x => 1, (key, g) => new
                {
                    AvgFormCompletionTime = 360,
                    AvgProcessingTime = 90,
                    ApprovalRate = .75
                });

Firstly 'key' was added making (g), (key, g).

Secondly, linq only accepts parameterless constructors, which the one on my question wasn't.

To convert the final anonymous property, I added this statement back in at the end:

return new ApplicationStats(q4.AvgFormCompletionTime, q4.AvgProcessingTime, q4.ApprovalRate);

Upvotes: 1

Related Questions