Allstar
Allstar

Reputation: 439

Calculation on List<> subset with Linq Skip and Take

As according to this stack question: How to calculate the rolling average of a C# array list?

You can take a running average of values in a normal list like this:

List<int> numlist = new List<int>();
List<double> averages = Enumerable.Range(0, numlist.Count - 3).
                          Select(i => numlist.Skip(i).Take(4).Average()).
                          ToList();

My Question: I want to be able to do that on a specific subset of a class list:

public class Data_Raw
{
    public DateTime DateDataRaw { set; get; }
    public double PriceRaw { set; get; }
    public double PercentageReturnsRaw { set; get; }

    public Data_Raw(DateTime _dateDataRaw,double _priceRaw, double _percentageReturnsRaw)
    {
        DateDataRaw = _dateDataRaw;                     //1
        PriceRaw = _priceRaw;
        PercentageReturnsRaw = _percentageReturnsRaw;
    }
}

List<Data_Raw> myRawData = new List<Data_Raw>();

I want to calculate the average of the PriceRaw data, within the class list which is myRawData.

EDIT:

If this is the data for PriceRaw:

myRawData[0].PriceRaw=2
myRawData[1].PriceRaw=3
myRawData[2].PriceRaw=4
myRawData[3].PriceRaw=5

How do I get the average value of the last three PriceRaw values which is = (3+4+5)/3 = 4. It is only available directly after myRawData.Skip

Skip is not available if I try to append it to myRawData[].PriceRaw.Skip

This stack question gets me closer, but can't figure it out: Linq query a List of objects containing a list of object

Upvotes: 0

Views: 909

Answers (2)

Daniel Hilgarth
Daniel Hilgarth

Reputation: 174329

Simply select the value you need into your numList (see first line):

var numList = myRawData.Select(x => x.PriceRaw).ToList();
List<double> averages = Enumerable.Range(0, numlist.Count - 3).
                      Select(i => numlist.Skip(i).Take(4).Average()).
                      ToList();

An alternate way could be this:

List<double> averages = Enumerable.Range(0, myRawData.Count - 3).
                      Select(i => myRawData.Skip(i).Take(4).Select(x => x.PriceRaw).Average()).
                      ToList();

Upvotes: 0

Cetin Basoz
Cetin Basoz

Reputation: 23797

I think it would be easier for you to manage it if you use comprehension syntax. ie:

void Main()
{
    List<Data_Raw> myRawData = new List<Data_Raw> {
       new Data_Raw(new DateTime(2018,1,1), 2, 1),
       new Data_Raw(new DateTime(2018,1,2), 3, 1),
       new Data_Raw(new DateTime(2018,1,3), 4, 1),
       new Data_Raw(new DateTime(2018,1,4), 5, 1),
       new Data_Raw(new DateTime(2018,1,5), 6, 1),
       new Data_Raw(new DateTime(2018,1,6), 7, 1),
       new Data_Raw(new DateTime(2018,1,7), 8, 1),
    };

    var groupSize = 3;
    var result = from i in Enumerable.Range(0, myRawData.Count() - (groupSize - 1))
                 let myGroup = myRawData.Skip(i).Take(groupSize)
                 select new
                 {
                     Values = string.Join(",", myGroup.Select(rd => rd.PriceRaw.ToString())),
                     Average = myGroup.Average(rd => rd.PriceRaw)
                 };
}

public class Data_Raw
{
    public DateTime DateDataRaw { set; get; }
    public double PriceRaw { set; get; }
    public double PercentageReturnsRaw { set; get; }

    public Data_Raw(DateTime _dateDataRaw, double _priceRaw, double _percentageReturnsRaw)
    {
        DateDataRaw = _dateDataRaw;                     //1
        PriceRaw = _priceRaw;
        PercentageReturnsRaw = _percentageReturnsRaw;
    }
}

Upvotes: 1

Related Questions