【问题标题】:c# lambda group datalist to column from row to create new collection listc# lambda group datalist to column from row to create new collection list
【发布时间】:2021-10-21 04:35:51
【问题描述】:

我需要按 DateUserId

将此数据列表分组到新的集合列表
Id Date TypeId Value UserId
1 2021-10-19 1 12 5
2 2021-10-19 2 15 5
3 2021-10-20 1 20 20
4 2021-10-20 2 11 20
5 2021-10-20 3 14 20
6 2021-10-20 1 19 18
7 2021-10-20 4 15 20
8 2021-10-20 1 18 19

C# Lambda 中的新集合列表

Date UserId TypeId1 TypeId2 TypeId3 TypeId4
2021-10-19 5 12 15
2021-10-20 18 19
2021-10-20 19 18
2021-10-20 20 20 11 14 15

第一个我代码:var groupTranDate = db.System_Transactions.GroupBy(g => new { g.Transaction_Date,g.User_Id }).ToList();

真实结果,但我无法将数据获取到新集合 Please click here to view result image for my code

【问题讨论】:

    标签: c# model-view-controller lambda


    【解决方案1】:

    你必须明白,GroupBy返回IEnumerable<IGrouping<TKey, TSource>>,所以你要把IGrouping转换成IEnumerable

    var groupTranDate = db.System_Transactions
                                    .GroupBy(g => new MyGroupedClass 
                                    {
                                        UserId = g.UserId, 
                                        Transaction_Date = g.Transaction_Date
                                    )})
                                    .Select(x => x.Where(x => x))
                                    .Select(x => x);
    

    如何获得新的收藏:

    List<MyGroupedClass> ts = new List<MyGroupedClass>();
    
    foreach(var item in groupTranDate)
    {
        ts.AddRange(item);
    }
    

    【讨论】:

    • 您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center
    【解决方案2】:

    看起来很合理,我可能会更进一步,将组的结果列表转换为专为该工作设计的类:

    record X(
      DateTime Date, 
      int UserId, 
      int? TypeId1,
      int? TypeId2,
      int? TypeId3,
      int? TypeId4
    ){
        public X(IGrouping<(DateTime T,int U),System_Transaction> y):this(y.Key.T, y.Key.U, null, null, null, null){
            foreach(var x in y){
                _ = x.Type_Id switch {
                    1 => TypeId1 = x.Value,
                    2 => TypeId2 = x.Value,
                    3 => TypeId3 = x.Value,
                    4 => TypeId4 = x.Value,
                    _ => throw new NotImplementedException($"Type Id {x.Type_Id} is not handled")
                };
             }
        }
    

    然后加入你的分组

    var groupTranDate = db.System_Transactions
      .GroupBy(g => (g.Transaction_Date,g.User_Id))
      .Select(g => new X(g))
      .ToList();
    

    记录就像一个类,只是写出来更简单;它有一个构造函数,可以转换 GroupBy 生成的分组;基本上构造函数首先调用另一个构造函数(你看不到,因为 C# 在幕后生成它)传递事务日期和用户是 - 设置这些属性。接下来,构造函数遍历分组(其行为类似于 YourClass 的列表,无论您的类被称为什么 - 请将类型名称更改为您的真实类名称),如果 Type_Id 为 1,则属性 TypeId1 最终分配了值等 在循环结束时,无论有多少项目(1 到 4 之间),您都会将 TypeIdX 属性设置为值(如果没有值,则保持为空)

    LINQ 查询所需的唯一调整是将分组从匿名类型更改为元组,因为在创建它们的上下文之外使用 AT 很痛苦,并且使用 Select 将分组到我们的记录 X

    如果您希望该记录在更熟悉的东西/在旧 .NET 中工作的类中,它看起来像:

    class X(
      public DateTime Date {get;set;}, 
      public int UserId {get;set;},
      public int? TypeId1 {get;set;},
      public int? TypeId2 {get;set;},
      public int? TypeId3 {get;set;},
      public int? TypeId4 {get;set;}
    ){
        public X(IGrouping<(DateTime T,int U),System_Transaction> y){
            Date = T;
            UserId = U;
            foreach(var x in y){
                if(x.Type_Id == 1) TypeId1 = x.Value;
                else if(x.Type_Id == 2) TypeId2 = x.Value;
                else if(x.Type_Id == 3) TypeId3 = x.Value;
                else if(x.Type_Id == 4) TypeId4 = x.Value;
                else throw new NotImplementedException($"Type Id {x.Type_Id} is not handled");
             }
        }
    

    有一些方法可以让字典等变得可爱,以避免像那里那样在循环中写出巨大的 if/switch 块,但你仍然必须写出属性,除非你打算制作table 可以由具有 N 个键的字典驱动的仅显示事物,而不是您在代码中引用为具有属性 TypeId4 的某个 X 的对象。

    【讨论】:

      猜你喜欢
      • 2022-12-02
      • 2014-07-26
      • 1970-01-01
      • 1970-01-01
      • 2020-06-12
      • 2022-12-28
      • 2022-12-28
      • 2022-12-01
      • 1970-01-01
      相关资源
      最近更新 更多