I'm new to C# and This is the first time I'm using LINQ queries. I have a Dictionary as Dictionary<(int MeterId, DateTime TimeStamp), float>
With data as follows,
<(10411, 12/1/2022 12:30:00 AM), 5700>
<(10411, 13/1/2022 12:30:00 AM), 5200>
<(10412, 12/1/2022 12:30:00 AM), 200>
Then there's a method to add them to a list with meterId and average value for each day of week. I'm using LINQ queries to calculate the averages and get them to a list.
public static List<AveragedMeter> CalculateAverageValues(Dictionary<(int MeterId, DateTime TimeStamp), float> groupedMeterValues)
{
var lstResult = groupedMeterValues
.GroupBy(m => new { m.Key.MeterId, m.Key.TimeStamp.DayOfWeek })
.Select(g => new AveragedMeter
{
MeterId = g.Key.MeterId,
AverageMondayValue,
AverageTuesdayValue,
AverageWednesdayValue,
AverageThursdayValue,
AverageFridayValue,
AverageSaturdayValue,
AverageSundayValue
})
.ToList();
return lstResult;
}
I'm not certain how to get for these average values. My AveragedMeter class is as follows,
class AveragedMeter
{
public int MeterId { get; set; }
public float AverageMondayValue { get; set; }
public float AverageTuesdayValue { get; set; }
public float AverageWednesdayValue { get; set; }
public float AverageThursdayValue { get; set; }
public float AverageFridayValue { get; set; }
public float AverageSaturdayValue { get; set; }
public float AverageSundayValue { get; set; }
}
CodePudding user response:
You could filter the data by DayOfWeek inside your select instead of grouping the dictionary, something like this:
static List<AveragedMeter> CalculateAverageValues(Dictionary<(int MeterId, DateTime TimeStamp), float> groupedMeterValues)
{
var lstResult = groupedMeterValues
.GroupBy(m => m.Key.MeterId)
.Select(g => new AveragedMeter
{
MeterId = g.Key,
AverageMondayValue = g.Where(n => n.Key.TimeStamp.DayOfWeek == DayOfWeek.Monday).Average(n => n.Value),
AverageTuesdayValue = g.Where(n => n.Key.TimeStamp.DayOfWeek == DayOfWeek.Tuesday).Average(n => n.Value),
AverageWednesdayValue = g.Where(n => n.Key.TimeStamp.DayOfWeek == DayOfWeek.Wednesday).Average(n => n.Value),
AverageThursdayValue = g.Where(n => n.Key.TimeStamp.DayOfWeek == DayOfWeek.Thursday).Average(n => n.Value),
AverageFridayValue = g.Where(n => n.Key.TimeStamp.DayOfWeek == DayOfWeek.Friday).Average(n => n.Value),
AverageSaturdayValue = g.Where(n => n.Key.TimeStamp.DayOfWeek == DayOfWeek.Saturday).Average(n => n.Value),
AverageSundayValue = g.Where(n => n.Key.TimeStamp.DayOfWeek == DayOfWeek.Sunday).Average(n => n.Value),
})
.ToList();
return lstResult;
}
CodePudding user response:
The accepted the answer is not performance optimal because it iterates all values 7 times (excluding the GroupBy()
). I propose a solution the iterates the values only twice:
static List<AveragedMeter> CalculateAverageValues(
Dictionary<(int MeterId, DateTime TimeStamp), float> groupedMeterValues)
=> groupedMeterValues
.GroupBy(g => g.Key.MeterId)
.Select(g => CalculateAverageDays(
g.Key,
g.ToLookup(x => x.Key.TimeStamp.DayOfWeek, x => x.Value)))
.ToList();
static AveragedMeter CalculateAverageDays(
int meterId,
ILookup<DayOfWeek, float> valuesPerDay)
=> new AveragedMeter {
MeterId = meterId,
AverageMondayValue = valuesPerDay[DayOfWeek.Monday].DefaultIfEmpty().Average(),
AverageTuesdayValue = valuesPerDay[DayOfWeek.Tuesday].DefaultIfEmpty().Average(),
AverageWednesdayValue = valuesPerDay[DayOfWeek.Wednesday].DefaultIfEmpty().Average(),
AverageThursdayValue = valuesPerDay[DayOfWeek.Thursday].DefaultIfEmpty().Average(),
AverageFridayValue = valuesPerDay[DayOfWeek.Friday].DefaultIfEmpty().Average(),
AverageSaturdayValue = valuesPerDay[DayOfWeek.Saturday].DefaultIfEmpty().Average(),
AverageSundayValue = valuesPerDay[DayOfWeek.Sunday].DefaultIfEmpty().Average()
};