由相似和相反的元素组成

时间:2013-10-19 06:24:37

标签: c#

我有以下类型的数据:

   Acct    Date     From    To     Amt
1) ABC     today    USD     CAD    100 
2) ABC     today    CAD     USD   -250 
3) DEF     today    GBP     AUD    300 
4) DEF     today    GBP     AUD    200


我需要对数据进行分组并对金额求和。要做到这一点,我需要净化对方货币,以便结果应该是:

   Acct    Date     From    To     Amt
1) ABC     today    CAD     USD   -150 
2) DEF     today    GBP     AUD    500 


我正在使用.Net 3.5。 我只能使用与货币相同的净数据:

var net = data.GroupBy(x=> new { x.Acct, x.Date, x.From, x.To})
.Select new {y.Key.Acct, y.Key.Date, y.Key.From, y.Key.To, Net = y.Sum(x => x.Amt)});

有没有办法净化相似和相反的货币?

1 个答案:

答案 0 :(得分:0)

编辑结束对第二个代码块的解释和粗体的重要免责声明。

var query = from acct in accts
    select new
    {
        acct.From,
        acct.To,
        acct.Amount,
        FirstOrientedAmount = ((acct.From.CompareTo(acct.To) == -1 && acct.Amount < 0) ||
            (acct.From.CompareTo(acct.To) >= 0 && acct.Amount > 0)) ? acct.Amount : 0,
        SecondOrientedAmount = ((acct.From.CompareTo(acct.To) >= 0 && acct.Amount < 0) ||
            (acct.From.CompareTo(acct.To) == -1 && acct.Amount > 0)) ? acct.Amount * -1 : 0
    } into r
    group r by new
    {
        First = (r.From.CompareTo(r.To) == -1 ? r.From : r.To),
        Second = (r.From.CompareTo(r.To) == -1 ? r.To : r.From)
    } into g
    select new
    {
        First = g.Sum(acctval => acctval.FirstOrientedAmount) + g.Sum(acctval => acctval.SecondOrientedAmount) > 0 ? g.Key.Second : g.Key.First,
        Second = g.Sum(acctval => acctval.FirstOrientedAmount) + g.Sum(acctval => acctval.SecondOrientedAmount) > 0 ? g.Key.First : g.Key.Second,
        FTotal = g.Sum(acctval => acctval.FirstOrientedAmount),
        STotal = g.Sum(acctval => acctval.SecondOrientedAmount),
        Total = g.Sum(acctval => acctval.FirstOrientedAmount) + g.Sum(acctval => acctval.SecondOrientedAmount),
    };

这给出了:

CAD USD -150
GBP AUD 500

编辑:我正在遗弃旧代码,因为我并不完全理解这些要求,但我发布了一些不依赖于编译器来优化它的东西:

var query = from p in accts
    select new
    {
        p.From,
        p.To,
        p.Amount,
        OrientedAmount = ((p.From.CompareTo(p.To) == -1 && p.Amount < 0) ||
            (p.From.CompareTo(p.To) >= 0 && p.Amount > 0)) ? p.Amount : p.Amount * -1
    } into r
    group r by new
    {
        First = (r.From.CompareTo(r.To) == -1 ? r.From : r.To),
        Second = (r.From.CompareTo(r.To) == -1 ? r.To : r.From)
    } into g
    select new
    {
        g.Key.First,
        g.Key.Second,
        Total = g.Sum(val => val.OrientedAmount)
    } into last
    select new
    {
        First  = last.Total > 0 ? last.Second : last.First,
        Second = last.Total > 0 ? last.First : last.Second,
        Total = last.Total
    };
  1. 首先将所有金额定向到其From帐户是按字典顺序排列的最大货币名称的交易。如果当前交易行有效地将资金转移到按字典顺序排列的最小货币名称,则会在金额上翻转该符号。

  2. 现在按交易中的帐户进行分组,按字典顺序排序。

  3. 选择总数(这样我们只需要执行一次)。为此,请添加所有定向金额。

  4. 如果总价值是正数(就像我这样做的话),我们有一个净值进入按字典顺序排列的最大货币名称。如果是负数,则净值将进入按字典顺序排列的最小货币名称。

  5. 但是,我不相信这些是好的要求(或者我误解了原来的要求)。如果你看看这个问题正在解决什么,它将“A B卖”,“A B买”,“B买”和“B卖”合并为一组。在这种情况下,“A B 100”表示“A B -100”。第一种方法购买100 A.第二种方式是将100 B卖给A.如果你看看这个问题的解决方式 它们是同一个东西。 但实际上, 他们不是一回事。 卖100 B不会给你与购买100 A意愿相同的A量。您需要汇率来规范化。