Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using already computed element

Tags:

c#

linq

I find myself repeating calculations within a linq statements and I was wondering whether I can access already computed elements somehow. This is what I m doing:

var result = testdata.GroupBy(a => new { a.reportinggroup, a.commodity, a.timestep.Year })
                     .Select(g => new EndResult
                            {
                                rundate = rundate.ToShortDateString(),
                                price = g.Sum(a => (a.timestep.ispeak()) ? a.price : 0) / g.Sum(a => (a.timestep.ispeak()) ? 1 : 0),
                                valueposition = g.Sum(a => (a.timestep.ispeak()) ? a.position * a.price : 0) / (g.Sum(a => (a.timestep.ispeak()) ? a.price : 0) / g.Sum(a => (a.timestep.ispeak()) ? 1 : 0)),

                            }).ToList();

Which works fine.

This is what I would like to be doing:

var result = testdata.GroupBy(a => new { a.reportinggroup, a.commodity, a.timestep.Year })
                     .Select(g => new EndResult
                            {
                                rundate = rundate.ToShortDateString(),
                                price = g.Sum(a => (a.timestep.ispeak()) ? a.price : 0) / g.Sum(a => (a.timestep.ispeak()) ? 1 : 0),
                                valueposition = g.Sum(a => (a.timestep.ispeak()) ? a.position * a.price : 0) / price,           
                            }).ToList();

where the price is the price I computed just after rundate. Can I access this somehow?

like image 431
nik Avatar asked Sep 30 '22 20:09

nik


2 Answers

You can select an anonymous type first to store this value:

result = testdata.GroupBy(a => new { a.reportinggroup, a.commodity, a.timestep.Year })
.Select(g => new { 
    rundate = rundate.ToShortDateString(), 
    price = g.Sum(a => (a.timestep.ispeak()) ? a.price : 0) / g.Sum(a => (a.timestep.ispeak()) ? 1 : 0),
    group = g
})
.Select(x => new EndResult
{
    rundate = x.rundate,
    price = x.price,
    valueposition = x.group.Sum(a => (a.timestep.ispeak()) ? a.position * x.price : 0) / x.price
}).ToList();

Another way is using "real" code:

result = testdata.GroupBy(a => new { a.reportinggroup, a.commodity, a.timestep.Year })
.Select(g => { 
    var price = g.Sum(a => (a.timestep.ispeak()) ? a.price : 0) / g.Sum(a => (a.timestep.ispeak()) ? 1 : 0);
    EndResult endRes = new EndResult { 
        rundate = rundate.ToShortDateString(),
        price = price,
        valueposition = x.group.Sum(a => (a.timestep.ispeak()) ? a.position * price : 0) / price)
    };
    return endRes;
}).ToList();
like image 100
Tim Schmelter Avatar answered Oct 03 '22 09:10

Tim Schmelter


By using the query syntax (from), you can use the let clause:

 var result = (from g in  testdata.GroupBy(a => new { a.reportinggroup, a.commodity, a.timestep.Year })
               let price = g.Sum(a => (a.timestep.ispeak()) ? a.price : 0) / g.Sum(a => (a.timestep.ispeak()) ? 1 : 0)
               select new EndResult
               {
                   rundate = rundate.ToShortDateString(),
                   price = price,
                   valueposition = g.Sum(a => (a.timestep.ispeak()) ? a.position * a.price : 0) / price,
                }).ToList();
like image 33
Me.Name Avatar answered Oct 03 '22 11:10

Me.Name