Linq Groupby,Union和Sum汇总了多个集合中的数据

时间:2013-06-25 14:44:53

标签: c# .net linq

简介

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

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

Point more有3个属性date,int,decimal

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<Point>

示例数据解释问题

  • 属性Date和PTE很常见
    • 按日期,PTE对库存接受进行分组,并对bidVolume和OfferVolume
    • 求和
    • 检查StockVolume是否有StockAcceptance中的日期
    • 如果是,请将StockVolume中pte的交易量与StockAcceptance中的bidVolume和OfferVolume相加,得出结果。

enter image description here

我已经开始编写一个解决方案,但是使用了太多的时间变量和foreach循环。应该可以使用Linq更好地实现这一点,那里的任何Linq专家都愿意分享一些意见吗?

2 个答案:

答案 0 :(得分:3)

假设您有以下内容:

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
    });

答案 1 :(得分:1)

//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);