VB.NET get average from a range of values from a sortedlist (sortedlist.average)

294 views Asked by At

I have a sortedlist like this;

public MeasuredValues as SortedList(Of DateTime, Double)

I throw in a bunch of values. For example;

MeasuredValues.add(New DateTime(2010, 1, 1),33)
MeasuredValues.add(New DateTime(2011, 1, 1),13)
MeasuredValues.add(New DateTime(2012, 1, 1),233)
MeasuredValues.add(New DateTime(2013, 1, 1),331)
MeasuredValues.add(New DateTime(2014, 1, 1),732)
MeasuredValues.add(New DateTime(2015, 1, 1),123)

Now I want to get the avarage of this values, say from 2011 to 2013. (ofcourse my real situation has much more values)

I've seen the sortedlist has a extension method called 'Avarage' ; https://msdn.microsoft.com/en-us/library/bb534965(v=vs.110).aspx

But I can't find any clear examples. I like VB.NET, but C# examples are also welcome...

I know I need to implement a function, but I don't know how. MSDN does not supply any example. Also, is this the best/fastest way to do it?, or is there a better alternative...

Thanks in advance...


Update: I've tried this;

            Dim MyAverage As Double = MeasuredValues.Average(Function(measure) CDate(measure.Key) >= ThisStepBeginTime And CDate(measure.Key) <= ThisStepEndTime)

But it only delivers a occasional -0,1

This 'one-line functions' are new for me, what am I doing wrong?


Update 2: My example was a over simplefied example of the real problem. I'm trying to draw a graph, where every pixel represents a timespan. Like this;

    For XCounter As Integer = 0 To MyBase.Width
        Dim ThisStepBeginTime As DateTime = First.AddTicks(XCounter * TimeStep.Ticks)
        Dim ThisStepEndTime As DateTime = First.AddTicks((XCounter + 1) * TimeStep.Ticks)

        For Each MySerie In Me.AllSeries.Values

            Dim MyAverage As Double = MySerie.Where(Function(measure) CDate(measure.Key) >= ThisStepBeginTime And CDate(measure.Key) <= ThisStepEndTime).Average(Function(measure) measure.Value)

            e.Graphics.DrawLine(Pens.Red, XCounter, CInt((Me.Height / MySerie.HighestValue) * MyAverage), XCounter, 0)
        Next
    Next

This results in;

Sequence contains no elements

Because some of the steps don't have a value....

1

There are 1 answers

10
Keith Mifsud On BEST ANSWER

I think you can filter the list first and then get the average:

MeasuredValues _
.Where(Function(measure) cDate(measure.Key) >= dateFrom And cDate(measure.Key) <= dateTo) _
.Average(Function(measure) measure.Value)

REGARDING UPDATE 2:

If I understand the new issue corrently, you're getting an error on the Average if Where returns no elements. I know you can add .DefaultIfEmpty in between however I don't know how that would affect the Average function:

MeasuredValues _
.Where(Function(measure) cDate(measure.Key) >= dateFrom And cDate(measure.Key) <= dateTo) _
.DefaultIfEmpty() _
.Average(Function(measure) measure.Value)

I'm expecting the DefaultIfEmpty to return an empty element Of(DateTime, double) and thus averaging to 0