【问题标题】:Linq Groupby, Union and Sum to aggregate data in multiple collectionsLinq Groupby、Union 和 Sum 聚合多个集合中的数据
【发布时间】:2013-06-25 23:52:50
【问题描述】:

简介

1.我有一个StockVolume 类,它有一个属性Points,类型为ObservableCollection<Point>

public class StockVolume
{
    public ...
    public ObservableCollection<Point> Points {get; set;}
    public ...
}

Point还有date、int、decimal 3个属性

public class Point
{
    public DateTime Date {get; set;}
    public int Pte {get; set;}
    public decimal Volume {get; set;}
}

2.我有另一个类 StockAcceptance 有一些属性,

public class StockAcceptance
{
    public DateTime Date {get; set;}
    public int PTE {get; set;}
    public decimal BidVolume {get; set;}
    public decimal OfferVolume {get; set;}
}

3.结果需要加载到ObservableCollection&lt;Point&gt;

解释问题的示例数据

  • 属性Date和PTE是通用的
    • 按日期、PTE 对股票承兑进行分组,并对 bidVolume 和 OfferVolume 求和
    • 检查 StockVolume 在 StockAcceptance 中是否有日期
    • 如果是这样,将 StockVolume 中 pte 的交易量与 StockAcceptance 中的 bidVolume 和 OfferVolume 相加得出结果。

我已经开始编写解决方案,但是我使用了太多临时变量和 for、foreach 循环。这应该可以使用 Linq 以更好的方式实现,有任何 Linq 专家愿意分享一些输入吗?

【问题讨论】:

  • 我认为最后一步不正确:您正在检查StockVolume 是否在StockAcceptance 中具有日期 PTE,然后您正在执行@987654329 @。另外,对于第一个示例,生成的 Volume 应该是 -19 而不是 -21,对吧?
  • 您好 Andre,如果 StockAcceptance 有 StockVolume 中日期的数据,我只会对 StockVolume 和 StockAcceptance 求和。音量将为 -21,因为 newVolume = -20-(-4)-5 = -21。
  • 积分的日期/PTE 组合(在 StockVolume 中)是唯一的吗?
  • PTE 将始终是上述特定的。日期会改变。但是 Date,PTE 一起在 StockVolume 中是独一无二的。

标签: c# .net linq


【解决方案1】:

假设你有以下几点:

IEnumerable<StockAcceptance> accept = ...;
StockVolume volume = ...;

你应该从最里面,向外工作。您需要处理的第一件事是对股票承兑汇票进行分组:

var stockAccept = accept.GroupBy(a => new { a.Date, a.PTE },
    (k, g) => new { k.Date, k.PTE, 
        BidVolume = g.Sum(x => x.BidVolume), 
        OfferVolume = g.Sum(x => x.OfferVolume)
    });

这为您提供了DatePTE 的分组以及适当的总和。

您也可以对StockVolume 点执行相同操作:

var stockVolume = volume.GroupBy(v => new { v.Date, v.PTE },
    (k, g) => new {
        k.Date,
        k.PTE,
        Volume = g.Sum(x => x.Volume)
    });

现在你有了两个组,你可以通过DatePTE 的键加入得到最终结果:

IEnumerable<Point> result = stockAccept.Join(stockVolume, 
    o => new { o.Date, o.PTE },
    i => new { i.Date, i.PTE }, 
    (o, i) => new Point { 
        Date = o.Date, 
        PTE = o.PTE, 
        Volume = o.BidVolume + o.OfferVolume + i.Volume
    });

【讨论】:

    【解决方案2】:
    //Group the stock acceptance by Date, PTE and sum the bidVolume and OfferVolume
    var groupStock=listStock.GroupBy(s=>new {s.Date,s.PTE})
                    .Select(g=>new StockAcceptance
                           {
                                Date=g.Key.Date,
                                PTE=g.Key.PTE,
                                BidVolume=g.Sum(x=>x.BidVolume),
                                OfferVolume=g.Sum(x=>x.OfferVolume)
                           });
     StockVolume sv; 
    
     //get result you want:
     var result=from p in sv.Points
                   join s in groupStock
                   on new {Date=p.Date,PTE=p.Pte} equals new {Date=s.Date,PTE=s.PTE} into leftGroup
                   from s in leftGroup.DefaultIfEmpty()
                   select new Point
                   {
                     Date=p.Date,
                     Pte=p.Pte,
                     Volume=s==null?p.Volume:p.Volume-s.BidVolume-s.OfferVolume
                   };
    //fill result into ObservableCollection<Point> 
    ObservableCollection<Point> pCollection=new ObservableCollection<Point>(result);
    

    【讨论】:

      猜你喜欢
      • 2012-04-20
      • 2019-01-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-07
      • 2017-06-05
      • 2020-11-05
      相关资源
      最近更新 更多