我有一个MyObject列表如下:
public MyObject(reqVal, reqTime)
{
_value = reqVal;
_time = reqTime;
}
public double Value
{
get {return _value;}
}
public DateTime Time
{
get {return _time;}
}
var myList = new List<MyObject>();
myList.Add(new MyObject(100, new DateTime(2012, 03, 01, 10, 0, 0));
myList.Add(new MyObject(50, new DateTime(2012, 03, 01, 10, 3, 0));
myList.Add(new MyObject(10, new DateTime(2012, 03, 01, 10, 6, 0));
myList.Add(new MyObject(230, new DateTime(2012, 03, 01, 10, 9, 0));
....
如您所见,此列表包含一整天的值,每3分钟生成一个值。如何根据15分钟的大块找到以下内容:
所以如果第一个日期时间值是2012/03/01 10:00 我需要在10:00到10:15之间找到上面的4,然后在10:15到10:30之间找到下一个4,依此类推......
所以所有这些值都将根据它们的时间范围计算出来 例如,第二个maxVal或openVal将是10:15到10:30之间的maxVal和openVal
任何帮助将不胜感激,
感谢。
答案 0 :(得分:2)
我可能会使用这样的东西:
var end = start + TimeSpan.FromMinutes(15);
// Avoid querying more than once.
var matches = input.Where(x => x.Time >= start && x.Time < end)
.ToList();
// TODO: Consider what you want to do if there are no matches.
// (The code below would fail.)
var max = matches.Max(x => x.Value);
var min = matches.Min(x => x.Value);
var open = matches.First().Value;
var close = matches.Last().Value;
使用Aggregate
你可以在输入数据的一次传递中完成所有这些操作,而无需创建列表......但这会非常复杂。保持简单,然后进行基准测试,看看这个解决方案是否能为你做好 。
答案 1 :(得分:2)
非常类似于Jefferson先生的回复,但返回DateTime作为分组的关键字段,我认为您可能想要绘制这些结果。
List<MyObject> inputList = new List<MyObject>();
var resultSet = inputList
.GroupBy(i => i.GetStartOfPeriodByMins(15))
.Select( gr =>
new {
StartOfPeriod = gr.Key,
Min = gr.Min(item => item.Value),
Max = gr.Max(item => item.Value),
Open = gr.OrderBy(item => item.Time).First().Value,
Close = gr.OrderBy(item => item.Time).Last().Value
});
基于MyObject的定义,在对象本身上实现了GetStartOfPeriodByMins,尽管你可以把它放在任何地方:
public class MyObject
{
public double Value { get; set; }
public DateTime Time { get; set; }
public DateTime GetStartOfPeriodByMins(int numMinutes)
{
int oldMinutes = Time.Minute;
int newMinutes = (oldMinutes / numMinutes) * numMinutes;
DateTime startOfPeriod = new DateTime(Time.Year, Time.Month, Time.Day, Time.Hour, newMinutes, 0);
return startOfPeriod;
}
}
答案 2 :(得分:1)
您可以尝试对列表进行分组,其间隔为15分钟。这是一个有点快速和肮脏的示例(我已经更改了一些值来呈现更好的测试用例,TimeData
是与MyObject
)相同:
List<TimeData> myList = new List<TimeData>();
myList.Add(new TimeData(100, new DateTime(2012, 03, 01, 10, 0, 0)));
myList.Add(new TimeData(50, new DateTime(2012, 03, 01, 10, 3, 0)));
myList.Add(new TimeData(10, new DateTime(2012, 03, 01, 10, 35, 0)));
myList.Add(new TimeData(230, new DateTime(2012, 03, 01, 10, 46, 0)));
var grouped = myList.GroupBy(t => t.Time.Day.ToString()
+ "_" + t.Time.Month.ToString()
+ "_" + t.Time.Year.ToString()
+ "_" + t.Time.Hour.ToString() + "_"
+ (t.Time.Minute / 15).ToString())
.Select(gr => new { TimeSlot = gr.Key, Max = gr.Max(item => item.Value),
Min = gr.Min(item => item.Value),
Open = gr.OrderBy(g => g.Time).First().Value,
Close = gr.OrderBy(g => g.Time).Last().Value });
所以发生的事情是:
(t.Time.Minute / 15)
是整数除法,这意味着0到14之间的任何分钟值都等于0,15到29将是1,依此类推。你可以通过稍微改变GroupBy
来使运行更快(即使用类作为组密钥而不是为每个组构建一个字符串)。
更新:我通过向myList
添加10,000个元素以及值和分钟的随机值,为自己生成了一个更好的测试用例。我在.ToList()
代的末尾添加了grouped
,以确保延迟评估不是一个因素。它跑了34毫秒。我尝试了100,000个元素,它运行在226毫秒(由StopWatch
测量)。看起来性能不是一个大问题,除非资源受到约束,并且myList
中有数十万个元素。