Reputation: 1784
I m trying to do very similar linq statements but conditional on conditions they are slightly different. right now i just repeat the entire statement with small amendments but this should be possible much more concise. What I struggle with is to do the conditional groupby and also conditional select within the statement. My long version is:
class data
{
public string year;
public string quarter;
public string month;
public string week;
public string tariff;
public double volume;
public double price;
}
class results
{
public string product_code;
public string tariff;
public double volume;
public double price;
}
class Program
{
public static List<results> aggregationfunction(List<data> inputdata, string tarifftype, string timecategory)
{
List<results> returndata = new List<results>();
if (tarifftype.Equals("daynight") & timecategory.Equals("yearly"))
{
returndata = inputdata.GroupBy(a => new { a.tariff, a.year })
.Select(g => new results { product_code = g.Select(a => a.year).First(), tariff = g.Select(a => a.tariff).First(), volume = g.Sum(a => a.volume), price = g.Average(a => a.price) })
.ToList();
}
else if (tarifftype.Equals("allday") & timecategory.Equals("yearly"))
{
returndata = inputdata.GroupBy(a => new { a.year })
.Select(g => new results { product_code = g.Select(a => a.year).First(), tariff = "allday", volume = g.Sum(a => a.volume), price = g.Average(a => a.price) })
.ToList();
}
else if (tarifftype.Equals("daynight") & timecategory.Equals("quarterly"))
{
returndata = = inputdata.GroupBy(a => new { a.tariff, a.year, a.quarter })
.Select(g => new results { product_code = g.Select(a => a.year).First() + "_" + g.Select(a => a.quarter).First(), tariff = g.Select(a => a.tariff).First(), volume = g.Sum(a => a.volume), price = g.Average(a => a.price) })
.ToList();
}
else if (tarifftype.Equals("allday") & timecategory.Equals("quarterly"))
{
returndata = inputdata.GroupBy(a => new { a.year, a.quarter })
.Select(g => new results { product_code = g.Select(a => a.year).First() + "_" + g.Select(a => a.quarter).First(), tariff = "allday", volume = g.Sum(a => a.volume), price = g.Average(a => a.price) })
.ToList();
}
return returndata;
}
}
Any pointers would be appreciated. As you can see the group by and allocation of tariff and product code differ but this shouldnt mean I need to repeat it all, does it?
Upvotes: 1
Views: 3965
Reputation: 12797
Shorter code:
return inputdata
.GroupBy(a => new
{
a.year,
quarter = timecategory == "quarterly" ? a.quarter : string.Empty,
tariff = tarifftype == "daynight" ? a.tariff : "allday"
})
.Select(g => new results
{
product_code = g.Key.year + (string.IsNullOrEmpty(g.Key.quarter) ? "" : "_" + g.Key.quarter),
tariff = g.Key.tariff,
volume = g.Sum(a => a.volume),
price = g.Average(a => a.price)
})
.ToList();
Upvotes: 9
Reputation: 7724
The IGrouping<TKey, data>
items returned by inputdata.GroupBy
(where data
is the element type of inputdata
) will always implement IEnumerable<data>
regardless of the anonymous key type (which may be either {year} or {tariff, year} etc). So all the GroupBy values could be generalized to IEnumerable<IEnumerable<data>>
and you could then break it down to two steps:
IEnumerable<IEnumerable<data>> groups;
if (condition) {
groups = inputdata.GroupBy(a => new { a.year });
} else if (condition) {
groups = inputdata.GroupBy(a => new { a.tariff, a.year });
} else {
groups = inputdata.GroupBy(a => new { a.year, a.quarter });
}
returndata = groups.Select(...)
The conditional select should be simpler to implement because you can just use conditional operators inline, or expand the selector function to a multi-line block, e.g.:
.Select(g => {
var product_code = ...;
if (condition) {
product_code += "_" + ...;
}
return new results { product_code = product_code, ... };
})
Upvotes: 1