如何在c# linq中根据先前的数据创建与函数相关的新项
本文关键字:创建 数据 函数 新项 linq | 更新日期: 2023-09-27 18:02:10
List<History> data = new List<History>()
{
new History() {Symbol="a", Close = 1.0m, Date = new DateTime(2016, 2, 1) },
new History() {Symbol="a", Close = 1.1m, Date = new DateTime(2016, 2, 2) },
new History() {Symbol="a", Close = 1.4m, Date = new DateTime(2016, 2, 3) },
new History() {Symbol="a", Close = 1.7m, Date = new DateTime(2016, 2, 4) },
new History() {Symbol="a", Close = 1.8m, Date = new DateTime(2016, 2, 5) },
new History() {Symbol="a", Close = 1.0m, Date = new DateTime(2016, 2, 7) },
new History() {Symbol="a", Close = 1.1m, Date = new DateTime(2016, 2, 8) },
new History() {Symbol="a", Close = 1.4m, Date = new DateTime(2016, 2, 9) },
new History() {Symbol="a", Close = 1.7m, Date = new DateTime(2016, 2, 10) },
new History() {Symbol="a", Close = 1.8m, Date = new DateTime(2016, 2, 11) },
new History() {Symbol="b", Close = 1.6m, Date = new DateTime(2016, 2, 1) },
new History() {Symbol="b", Close = 1.2m, Date = new DateTime(2016, 2, 2) },
new History() {Symbol="b", Close = 1.4m, Date = new DateTime(2016, 2, 3) },
new History() {Symbol="b", Close = 1.8m, Date = new DateTime(2016, 2, 4) },
new History() {Symbol="b", Close = 1.2m, Date = new DateTime(2016, 2, 5) },
new History() {Symbol="b", Close = 2.0m, Date = new DateTime(2016, 2, 7) },
new History() {Symbol="b", Close = 1.4m, Date = new DateTime(2016, 2, 8) },
new History() {Symbol="b", Close = 1.4m, Date = new DateTime(2016, 2, 9) },
new History() {Symbol="b", Close = 1.0m, Date = new DateTime(2016, 2, 10) },
new History() {Symbol="b", Close = 2.8m, Date = new DateTime(2016, 2, 11) },
new History() {Symbol="c", Close = 2.0m, Date = new DateTime(2016, 2, 1) },
new History() {Symbol="c", Close = 2.1m, Date = new DateTime(2016, 2, 2) },
new History() {Symbol="c", Close = 1.4m, Date = new DateTime(2016, 2, 3) },
new History() {Symbol="c", Close = 2.7m, Date = new DateTime(2016, 2, 4) },
new History() {Symbol="c", Close = 1.2m, Date = new DateTime(2016, 2, 5) },
new History() {Symbol="c", Close = 1.3m, Date = new DateTime(2016, 2, 7) },
new History() {Symbol="c", Close = 2.2m, Date = new DateTime(2016, 2, 8) },
new History() {Symbol="c", Close = 1.3m, Date = new DateTime(2016, 2, 9) },
new History() {Symbol="c", Close = 2.6m, Date = new DateTime(2016, 2, 10) },
new History() {Symbol="c", Close = 1.9m, Date = new DateTime(2016, 2, 11) },
};
var StockGroupList = data
.GroupBy(o => o.Symbol)
.OrderBy(o => o.Key)
.ToList();
我想创建一个像
这样的新列表select new { Symbol, Close, Date, Vol};
这里Vol
是五天的标准差,例如Symbol="a"
在2016, 2, 5
的Vol
是2016, 2, 1
到2016, 2, 5
的close
的函数,前四天的Vol
(例如2016, 2, 1
到2016, 2, 4
)默认为Vol = 0
。
List<dynamic> NewData = new List<dynamic>
{
new History() {Symbol="a", Close = 1.0m, Date = new DateTime(2016, 2, 1), Vol = 0 },
new History() {Symbol="a", Close = 1.1m, Date = new DateTime(2016, 2, 2), Vol = 0 },
new History() {Symbol="a", Close = 1.4m, Date = new DateTime(2016, 2, 3), Vol = 0 },
new History() {Symbol="a", Close = 1.7m, Date = new DateTime(2016, 2, 4), Vol = 0 },
new History() {Symbol="a", Close = 1.8m, Date = new DateTime(2016, 2, 5), Vol = SD(XXX) },
new History() {Symbol="a", Close = 1.0m, Date = new DateTime(2016, 2, 7), Vol = SD(XXX) },
......
};
你可以把SD(xxx)
看作一个给定的函数,简单地表示十天的总和,但不要使用逐条输入的方法,因为实际上这里ten
可能会被大数据中的一个大数代替。此外,如果SD
遵循表单
using MathNet.Numerics.Statistics;
decimal OneStdDev = (decimal)(new DescriptiveStatistics(data.Select(o => (double)o.Close)).StandardDeviation);
我该怎么办?
我不确定我是否理解对了,但我认为你正在寻找这样的东西。(为了简单起见,我用Average
函数代替了StdDev函数)。
int dayspan = 5;
var result = from history in data
let lastCloses =
from history1 in data
where history.Symbol == history1.Symbol
&& history.Date >= history1.Date
&& history.Date - history1.Date <= TimeSpan.FromDays(dayspan)
select history1.Close
select new {
Symbol = history.Symbol,
Close = history.Close,
Date = history.Date,
Vol = lastCloses.Count() >= dayspan ? lastCloses.Average() : 0};
更新:如果不能依赖日期而想使用列表位置,则不能使用Linq查询语法,而是使用Linq方法语法:
int dayspan = 5;
var result = data.Select(
delegate(History history, int index)
{
decimal[] vol = data
.Select((history1, index1) => new {History = history1, Index = index1})
.Where(x => x.Index <= index
&& index - x.Index < dayspan
&& x.History.Symbol == history.Symbol)
.Select(x => x.History.Close).ToArray();
return new
{
Symbol = history.Symbol,
Close = history.Close,
Date = history.Date,
Vol = vol.Count() == dayspan ? vol.Average() : 0
};
});
出于可读性的考虑,也许使用简单的循环来解决这个问题比Linq:-)