Linq列表

时间:2014-12-30 22:58:29

标签: c# linq

class Bar
{
   public DateTime Time { get; set; }
   public double Price { get; set; }
}

class Instrument
{
   public List<Bar> Bars { get; set; }
   public string Name { get; set; }

   public Instrument(string name, string path) { 
      // set the Bars list here reading from files
   }
}

以下是我的课程的两个简化版本。我正在为货币创建自定义回测平台。目前的问题是切断我不会在每台仪器上都有价格数据的条形码。

我从XML文件中读取价格。

var xlinqBarLists = xlinqInstruments.Select(i => i.Bars);

基本上是

List<List<Bar>> xlinqBarLists

我想要做的是遍历每个单独的列表,找到最新的开始日期和最早的结束日期,然后在该时间窗口之外删除所有栏。我的黑客密码是

var xlinqInstruments = root.Elements("instrument").Select( a => 
   new Instrument( a.Element("name").Value, a.Element("path").Value ) );    

var xlinqBarLists = xlinqInstruments.Select(i => i.Bars);

DateTime latestStartDate = DateTime.MinValue;
DateTime earliestEndDate = DateTime.MaxValue;

foreach (List<Bar> bars in xlinqBarLists)
{
   if (bars.Min(b => b.Time) > latestStartDate)
      latestStartDate = bars.Min(b => b.Time);

   if (bars.Max(b => b.Time) < earliestEndDate)
       earliestEndDate = bars.Max(b => b.Time);
 }

foreach (List<Bar> barList in xlinqBarLists)
{
   var timeWindowBars = from bar in barList
                  where bar.Time >= latestStartDate && bar.Time <= earliestEndDate
                  select bar;

   // I need some way to overwrite the original Instrument.Bars property with timeWindowBars
   // Suggestions?
}

我可以通过跳过foreach循环来更快更有效地完成这项工作吗?

3 个答案:

答案 0 :(得分:0)

如果my comment above(我已在下面复制/粘贴)证明是这种情况,那么这是一个答案。

  

您是否要将每个乐器的Bars属性设置为a   列表仅包含最小值范围内的对象   所有Bar对象的结束日期和最长开始日期(包括   那些出现在其他仪器上的人?)

// Get the value of the earliest Bar.Time on each Instrument, and select the most recent of those.
DateTime latestStartDate = xlinqInstruments.Max(instrument => instrument.Bars.Min(bar => bar.Time));

// Get the value of the latest Bar.Time on each Instrument, and select the earliest of those.
DateTime earliestEndDate = xlinqInstruments.Min(instrument => instrument.Bars.Max(bar => bar.Time));

// Overwrite the Bars collection of each instrument with its contents truncated appropriately.
// I'd suggest doing this with a foreach loop as opposed to what I've provided below, but that's just me.
xlinqInstruments.ForEach(instrument => 
{
    instrument.Bars = instrument.Bars.Where(obj => obj.Time >= latestStartDate && obj.Time <= earliestEndDate).ToList();
});

ForEach方法要求您先在.ToList()集合上调用xlinqInstruments,这可能毫无价值。在我的代码中,我假设该集合已经实现为List<Instrument>

您可能也对linq&#39; Enumerable.SelectMany方法感兴趣。

  

Enumerable.SelectMany Method(IEnumerable,Func&gt;)

     

将序列的每个元素投影到IEnumerable,并将生成的序列展平为一个序列。

答案 1 :(得分:0)

有关最新的开始日期和最早的结束日期,您可以使用

DateTime latestStartDate = xlinqInstruments.Max(i => i.Bars.Min(bar => bar.Time));
DateTime earliestEndDate = xlinqInstruments.Min(i => i.Bars.Max(bar => bar.Time));

对于最后一部分,也许你想为'Instrument'添加一个无参数构造函数然后

var result = xlinqInstruments
                 .Select(i=>new Instrument()
                                    {
                                       Name = i.Name, 
                                       Bars = i.Bars.Where(bar => bar.Time >= latestStartDate 
                                                               && bar.Time <=earliestEndDate)
                                                    .ToList()
                                    });

答案 2 :(得分:-1)

在分配到ToList之前调用xlinqBarLists

var xlinqBarLists = xlinqInstruments.Select(i => i.Bars).ToList();

否则,您将一遍又一遍地解析相同的XML。

如果您希望稍后更新,请在创建ToList时调用xlinqInstruments