基于其他列,合并C#列表中一列的多个行

3

我有一个通用的 C# 列表 List<Result>,其中包含多个字段和多行数据,其类型为 RESULT,具体如下:

public class Result
{
    public int TrdID;
    public string Term;
    public double Price;
    public string Seller;
    public string Buyer;
    public bigint Quantity;
}

数据如下:

TrdID    Term      Price  Seller Buyer  Quantity
1000     201508      1     ABC    XYZ   10
1010     201508      2      ACB   PQR   10
1002     201507      1.5   ABX    PEW   20 
1002     201506      1.5   ABX    PEW   20
1002     201508      1.5   ABX    PEW   20

现在,我想处理上述数据并返回一个单一的唯一ID提供的结果。对于特定的ID,所有列都相同,除了Term。例如,我有三条记录ID 1002,我想将它们合并为一条记录,将Term转换为DateTime,并引入两个新列startDateEndDate,期望的结果如下所示。
   TrdID     StartDate     EndDate      Price  Seller Buyer  Quantity
    1000     08/01/2015    08/31/2015    1      ABC    XYZ   10
    1010     08/01/2015    08/31/2015    2      ACB    PQR   10
    1002     06/01/2015    08/31/2015    1.5    ABX    PEW   60 

从上面的数据可以看出,我有两列新列名为StartDateEndDate,而不是用于获取StartDateEndDate值的Term列。 此外,最后一行的Quantity发生了变化,它是一个特定ID的所有数量的总和,即,ID重复的次数*Quantity 这里有两种情况要解决 情况一: 如果特定ID(例如1000)只有一条记录,则StartDate将是该月的第一天,EndDate将是该月的最后一天,即08/01/2015和08/31/2015。 对Quantity没有更改 情况二: 如果特定ID(例如1002)有多个记录(所有期限都在一个序列中),则StartDate将是最小月份的第一天,即06/01/2015EndDate将是期限列中最高月份的最后一天,即08/31/2015Quantity= ID重复的次数*Quantity, 即 20*3=60 我的结果列表类型为
public class ProcessedResult
{
    public int TrdID;
    public DateTime StartDate;
    public DateTime EndDate;
    public double Price;
    public string Seller;
    public string Buyer;
    public bigint Quantity;
}

请问有什么好的方法来解决这个问题吗?


2
你尝试过什么?你卡在哪里了?GroupByMinMax似乎是合理的函数使用。 - D Stanley
1
当存在多个具有相同TrdID的记录时,价格、卖方、买方和数量的值是否对所有记录都相同? - Mike Hixson
1个回答

3
如果卖家和买家与您在帖子中展示的示例相同,您需要类似于以下内容:

假设卖家和买家与您在帖子中提到的一样,您需要像这样的东西:

var result = list.GroupBy( result => result.TrdID)
                 .Select( gr => {
                 var startDate = DateTime.ParseExact(gr.OrderBy(x => x.Term).First().Term, "yyyyMM", CultureInfo.InvariantCulture);
                 var endDate = DateTime.ParseExact(gr.OrderByDescending(x => x.Term).First().Term, "yyyyMM", CultureInfo.InvariantCulture);                      
                 return  new ProcessedResult
                 {
                     TrdID = gr.Key
                     StartDate = new DateTime(startDate.Year, startDate.Month, 1),
                     EndDate = (new DateTime(endDate.Year, endDate.Month, 1)).AddMonth(1).AddDays(-1),
                     Price = gr.First().Price,
                     Seller = gr.First().Seller,
                     Buyer = gr.First().Buyer,
                     Quantity = gr.Sum(x=>x.Quantity)
                 } 
             });

本质上,我们通过结果(列表包含您的结果)进行分组。技巧在于如何构造StartDateEndDate。我们对同一组中的行进行排序,并获取第一个以获取StartDate的字符串表示形式。然后,我们使用DateTime.ParseExact方法,因为我们知道DateTime的确切格式。至于EndDate,我们进行OrderByDescending,以便获得最后一个日期 - 我们可以进行OrderBy并获取最后一个元素,这是等效的。然后我们再次应用DateTime.ParseExact。


我对你的答案进行了微小的更改,以删除第一个注释中的异常DateTime.ParseExact(gr.OrderBy(x=>x.Term).First().Term,但这仍然没有给我正确的EndDate,而是给出了08/01/2015而不是08/31/2015 - DoIt
@Dev,你是正确的。我的错误 :(。请现在看一下。 - Christos
startDateendDate的格式都是yyyyMM,为什么你只用SubString(4,6)来处理'201508'呢? - DoIt
我对你的答案进行了一些修改以供审查,这些更改给了我正确的结果。 - DoIt
好的 :)!有哪些更改?你能分享一下吗?谢谢。 - Christos
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接