【问题标题】:C# LINQ query to sum rows by condition and add to existing listC# LINQ 查询按条件对行求和并添加到现有列表
【发布时间】:2021-12-02 14:13:40
【问题描述】:

我有以下数据列表。

 var data = new List<SummaryTabData>()
        {
            new SummaryTabData(){ LP = "LP_1", assetClass = "Asset_CFD_Long", avgSlippagePts = 54.23} ,
            new SummaryTabData(){ LP = "LP_1", assetClass = "Asset_FX_Long", avgSlippagePts = 61.41} ,
            new SummaryTabData(){ LP = "LP_1", assetClass = "Asset_FX_Short", avgSlippagePts = 11.48} ,
            new SummaryTabData(){ LP = "LP_1", assetClass = "Asset_CFD_Short", avgSlippagePts = 63.51} ,

            new SummaryTabData(){ LP = "LP_2", assetClass = "Asset_FX_Long",  avgSlippagePts = 6.51} ,            
            new SummaryTabData(){ LP = "LP_2", assetClass = "Asset_FX_Short", avgSlippagePts = 13.51}
        };

我的目标是为每种类型的 LP 的每对 Asset_CFD_long/Asset_CFD_shortAsset_FX_Long/Asset_FX_Short 添加一个额外的行。有时可能有 2 或 4 个资产类别,就像您在示例片段中看到的那样

最终的结果应该是这样的。

var data = new List<SummaryTabData>()
            {
                new SummaryTabData(){ LP = "LP_1", assetClass = "Asset_CFD_Long", avgSlippagePts = 54.23} ,
                new SummaryTabData(){ LP = "LP_1", assetClass = "Asset_CFD_Short", avgSlippagePts = 63.51} ,

                // that is the new row added to the collection for LP_1 CFD
                new SummaryTabData(){ LP = "LP_1", assetClass = "CFD_Total", avgSlippagePts = 117.74} ,

                new SummaryTabData(){ LP = "LP_1", assetClass = "Asset_FX_Long", avgSlippagePts = 61.41} ,
                new SummaryTabData(){ LP = "LP_1", assetClass = "Asset_FX_Short", avgSlippagePts = 11.48} ,

                // that is the new row added to the collection for LP_1 FX
                new SummaryTabData(){ LP = "LP_1", assetClass = "FX_Total", avgSlippagePts = 72.89} ,

                new SummaryTabData(){ LP = "LP_2", assetClass = "Asset_FX_Long",  avgSlippagePts = 6.51} ,
                new SummaryTabData(){ LP = "LP_2", assetClass = "Asset_FX_Short", avgSlippagePts = 13.51},

                // that is the new row added to the collection for LP_2 FX
                new SummaryTabData(){ LP = "LP_2", assetClass = "FX_Total", avgSlippagePts = 20.02},
            };

数据未排序。您是否知道可以执行此操作的某种 LINQ 查询,或者我应该使用传统的 for 循环方法?

【问题讨论】:

  • 要求有点奇怪。但是我不判断。基本上你会想要Groupby 然后Sum,。然后迭代结果,然后返回列表,找到每个组的最后一次出现,然后插入。
  • @TheGeneral 你能提供一个代码 sn-p 吗?
  • 如果没有排序,你怎么知道哪两个项目连接在一起?

标签: c# linq linq-to-sql


【解决方案1】:

要求有点奇怪,但假设是 LP 组可以以任何方式排序

更新

var groups = data
   .Select(x => new { Asset = x.assetClass.Split("_")[1], Summary = x })
   .GroupBy(x => new { x.Asset, x.Summary.LP });

var list = new List<SummaryTabData>();

foreach (var group in groups)
{
   list.AddRange(group.Select(x => x.Summary).ToList());

   list.Add(new SummaryTabData()
   {
      assetClass = $"{group.Key.Asset}_Total",
      LP = group.Key.LP,
      avgSlippagePts = group.Sum(x => x.Summary.avgSlippagePts)
   });

}

foreach (var item in list)
   Console.WriteLine($"{item.LP}, {item.assetClass}, {item.avgSlippagePts}");

输出

LP_1, Asset_FX_Short, 11.48
LP_1, Asset_FX_Long, 61.41
LP_1, FX_Total, 72.89
LP_1, Asset_CFD_Short, 63.51
LP_1, Asset_CFD_Long, 54.23
LP_1, CFD_Total, 117.74
LP_2, Asset_FX_Short, 13.51
LP_2, Asset_FX_Long, 6.51
LP_2, FX_Total, 20.02

在所有可能的情况下,还有其他方法可以做到这一点

Full Demo Here

【讨论】:

    【解决方案2】:
    using System;
    using System.Collections.Generic;using System.Linq;
    
    namespace TestConsoleApp
    {
        class Program
        {
            public class SummaryTabData
            {
                public string LP { get; set; }
                public string assetClass { get; set; }
                public double avgSlippagePts { get; set; }
            }
    
            public enum AssetClassType
            {
                Cfd,
                Fx
            }
    
            static void Main(string[] args)
            {
    
                var data = new List<SummaryTabData>()
                {
                    new SummaryTabData(){ LP = "LP_1", assetClass = "Asset_CFD_Long", avgSlippagePts = 54.23} ,
                    new SummaryTabData(){ LP = "LP_1", assetClass = "Asset_FX_Long", avgSlippagePts = 61.41} ,
    
                    new SummaryTabData(){ LP = "LP_1", assetClass = "Asset_FX_Short", avgSlippagePts = 11.48} ,
                    new SummaryTabData(){ LP = "LP_1", assetClass = "Asset_CFD_Short", avgSlippagePts = 63.51} ,
    
                    new SummaryTabData(){ LP = "LP_2", assetClass = "Asset_FX_Long",  avgSlippagePts = 6.51} ,
                    new SummaryTabData(){ LP = "LP_2", assetClass = "Asset_FX_Short", avgSlippagePts = 13.51}
                };
                var expectedResult = GetSummaries(data);
    
            }
    
            private static List<SummaryTabData> GetSummaries(List<SummaryTabData> data)
            {
                var datas = data.Select(x => new
                {
                    x.LP,
                    x.assetClass,
                    x.avgSlippagePts,
                    AssetClassType = x.assetClass.Contains("CFD") ? AssetClassType.Cfd : AssetClassType.Fx
                }).GroupBy(x => new { x.AssetClassType, x.LP })
                    .Select(x => new
                    {
                        assetClass = x.Key.AssetClassType == AssetClassType.Cfd ? "CFD_Total" : "FX_Total",
                        sum = x.Sum(z => z.avgSlippagePts),
                        Lp = x.Key.LP,
                        SummaryTabData = x.Select(z => new SummaryTabData()
                        {
                            assetClass = z.assetClass,
                            LP = z.LP,
                            avgSlippagePts = z.avgSlippagePts
                        })
                    }).ToList();
    
                List<SummaryTabData> result = new List<SummaryTabData>();
    
                foreach (var groupData in datas)
                {
                    result.AddRange(groupData.SummaryTabData);
    
                    result.Add(new SummaryTabData
                    {
                        assetClass = groupData.assetClass,
                        LP = groupData.Lp,
                        avgSlippagePts = groupData.sum
                    });
                }
    
                return result;
            }
        }
    }
    

    我认为这段代码可以帮助您解决问题, 我在代码的第一部分使用了 LINQ,在代码的最后一部分我无法避免使用 foreach。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-07-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多