Reputation: 1269
I'm new to linq and I'm trying to figure out how to change this linq query so that where it says prevPrice I'm accessing the Price from the previous row
var items = Data.Where(i => i.Date <= startingDate)
.Take(days + 1)
.Average(i => (i.Price - i.prevPrice) * i.Volume);
Upvotes: 1
Views: 728
Reputation: 1890
A little different approach. Linq is pretty much a simpler foreach
so you can use self-incrementing notation to get the element before or after.
int i = Data.Count();
int total = Data.Count();
Data = Data.OrderBy(o => o.Date);
var items = Data
.Where(o => o.Date <= startingDate)
.Take(days + 1)
.Average(o => (o.Price - (i == total ? (0 * (i--)) : Data.ElementAt(total - (i--)).Price)) * o.Volume);
Upvotes: 0
Reputation: 15794
Just use the overloaded Select()
call, like this:
var whatYouNeed = Data.Where(i => i.Date <= startingDate)
.Take(days + 1)
.ToList(); // I'm too lazy to be fancy, so I'm gonna preempt the LINQ here.
var items = whatYouNeed
.Select((item, index) =>
new
{
Current = item,
Previous = whatYouNeed[(index == 0 ? 0 : index - 1)]
})
.Average(item => (item.Current.Price - item.Previous.Price) * i.Volume);
Caveat: I'm making it so that if the first element is, literally, the first item in the collection, then it will put the first element (again) as Previous
. If you don't like that, then modify the ternary to do what you want it to do (or leave me a comment for a sample).
Hope this helps!
Upvotes: 0
Reputation: 463
Using MoreLinq's Pairwise
function, extra variables can be avoided:
var items = Data.Where(i => i.Date <= startingDate)
.Take(days + 1)
.Pairwise( ( previous, current ) => ( current.Price - previous.Price ) * current.Volume )
.Average();
Pairwise
provides the predecessor and current element as first and second arguments respectively to the resultSelector
function, except for the first element which is only provided as a predecessor to the second element.
Upvotes: 0
Reputation: 7803
This might work. I whipped it up real quick so check for consistency. I will edit when I have a moment:
var items = Data.Where(i => i.Date <= startingDate)
.Take(days + 1)
.Average(i => (
i.Price - Data.Where(p => p.Date < i.Date)
.OrderByDescending(p => p.Date)
.FirstOrDefault(p => o.Price)
) * i.Volume);
Upvotes: 0
Reputation: 3651
You can use aggregate
function to collect all calculations and than get an average from it
var results = new List<int>();
data.Where(i => i.Date <= startingDate).Take(days)
.Aggregate((a, b) =>
{
results.Add((b.price - a.price)*a.Volume);
return b;
});
var result = results.Average();
Upvotes: 2