如何高效将List对象按日期转换为多交易工具并排对比视图?
问题描述
我需要将STSmyTrade对象列表按entryTime日期重组,生成并排视图来按日对比不同交易工具(如eurusd、audusd)的交易数据,要把现有列表视图转换成目标并排视图。目前我用Dictionary<DateTime, ExpandoObject>实现,但需要手动为每个交易工具定义entryTime和entryPrice列,这个方案扩展性很差。有没有更高效的实现方式?
示例代码
void Main() { List<STSmyTrade> testoj = new List<STSmyTrade>(); STSmyTrade a1 = new STSmyTrade(); a1.instrument = "eurusd"; a1.entryPrice = 3; a1.entryTime = DateTime.Now.AddDays(1); testoj.Add(a1); STSmyTrade a2 = new STSmyTrade(); a2.instrument = "eurusd"; a2.entryPrice = 6; a2.entryTime = DateTime.Now.AddDays(2); testoj.Add(a2); STSmyTrade a3 = new STSmyTrade(); a3.instrument = "audusd"; a3.entryPrice = 3; a3.entryTime = DateTime.Now; testoj.Add(a3); STSmyTrade a4 = new STSmyTrade(); a4.instrument = "audusd"; a4.entryPrice = 6; a4.entryTime = DateTime.Now.AddDays(2); testoj.Add(a4); testoj.Dump(); // 按日期对比两种交易工具 Dictionary<DateTime, ExpandoObject> analysiscompare = new Dictionary<DateTime, ExpandoObject>(); foreach (STSmyTrade t in testoj ) { dynamic eo; if (!analysiscompare.ContainsKey(t.entryTime.Date)) { eo = new ExpandoObject(); eo.day = t.entryTime.Date.ToString("yyyy-MM-dd"); eo.eurusdentryTime = null; eo.eurusdentryPrice = null; eo.audusdentryTime = null; eo.audusdentryPrice = null; analysiscompare.Add(t.entryTime.Date, eo); } eo = analysiscompare[t.entryTime.Date]; switch (t.instrument) { case "eurusd": eo.eurusdentryTime = t.entryTime; eo.eurusdentryPrice = t.entryPrice; break; case "audusd": eo.audusdentryTime = t.entryTime; eo.audusdentryPrice = t.entryPrice; break; } } analysiscompare.Values.ToList().Dump("side_by_side_view"); } class STSmyTrade { public DateTime entryTime { get; set; } public string instrument { get; set; } public double entryPrice { get; set; } }
解决方案
可以通过分组+动态属性自动生成的方式解决扩展性问题,核心思路是先按日期分组,再针对每个分组里的交易工具,动态为ExpandoObject添加对应属性,无需提前硬编码工具名称:
优化后的代码
void Main() { List<STSmyTrade> testoj = new List<STSmyTrade>(); // 初始化测试数据 STSmyTrade a1 = new STSmyTrade { instrument = "eurusd", entryPrice = 3, entryTime = DateTime.Now.AddDays(1) }; STSmyTrade a2 = new STSmyTrade { instrument = "eurusd", entryPrice = 6, entryTime = DateTime.Now.AddDays(2) }; STSmyTrade a3 = new STSmyTrade { instrument = "audusd", entryPrice = 3, entryTime = DateTime.Now }; STSmyTrade a4 = new STSmyTrade { instrument = "audusd", entryPrice = 6, entryTime = DateTime.Now.AddDays(2) }; STSmyTrade a5 = new STSmyTrade { instrument = "gbpusd", entryPrice = 1.2, entryTime = DateTime.Now.AddDays(1) }; // 新增测试工具 testoj.AddRange(new[] {a1,a2,a3,a4,a5}); testoj.Dump(); // 1. 获取所有不重复的交易工具 var allInstruments = testoj.Select(t => t.instrument).Distinct().ToList(); // 2. 按日期分组并排序 var groupedByDate = testoj.GroupBy(t => t.entryTime.Date).OrderBy(g => g.Key); // 3. 生成并排视图数据 var analysisCompare = new List<dynamic>(); foreach (var dateGroup in groupedByDate) { dynamic eo = new ExpandoObject(); var eoDict = (IDictionary<string, object>)eo; eoDict["day"] = dateGroup.Key.ToString("yyyy-MM-dd"); // 初始化所有工具的属性为null foreach (var instrument in allInstruments) { eoDict[$"{instrument}entryTime"] = null; eoDict[$"{instrument}entryPrice"] = null; } // 填充当前日期下各工具的交易数据 foreach (var trade in dateGroup) { eoDict[$"{trade.instrument}entryTime"] = trade.entryTime; eoDict[$"{trade.instrument}entryPrice"] = trade.entryPrice; } analysisCompare.Add(eo); } analysisCompare.Dump("动态生成的并排视图"); } class STSmyTrade { public DateTime entryTime { get; set; } public string instrument { get; set; } public double entryPrice { get; set; } }
关键改进点
- 自动识别交易工具:通过
Distinct()获取所有存在的交易工具,无需手动添加新工具的属性 - 动态属性赋值:利用
IDictionary<string, object>操作ExpandoObject,避免硬编码switch分支 - 简洁的分组逻辑:用Linq的
GroupBy替代手动遍历字典,代码更易读维护 - 高扩展性:新增交易工具(如示例中的gbpusd)时,无需修改任何属性定义代码,自动生成对应列
内容的提问来源于stack exchange,提问作者junkone
相关产品推荐
相关产品推荐

