【问题标题】:How to order items within the group of anonymous type?如何订购匿名类型组内的项目?
【发布时间】:2021-01-31 11:53:39
【问题描述】:

我想将 Linq 查询的结果作为匿名对象组。组内的项目应按ID 字段排序。我可以通过 lambda 语法部分实现这一点,但无法获得匿名对象。所以我需要每个例子的一部分。 可执行代码:https://dotnetfiddle.net/cPJUN9

var res_g = (from dg in list
group new { dg.ID, dg.IDOperation, dg.IDDiagnosis } by dg.IDOperation
into dg_group
select dg_group);

lambda 语法

var res_g = list
.GroupBy(x => x.IDOperation)
.Select(x => x.OrderBy(x => x.ID)); // order dg by ID asc within group

【问题讨论】:

    标签: linq anonymous


    【解决方案1】:

    唉,你没有准确地描述你的要求,只是你想要一些匿名类型并且它们应该按 Id 排序。您的查询语法与您的方法语法不同。所以我只能举一个例子来创建你的匿名对象序列

    因此,您有一系列相似的项目,其中每个项目至少具有属性 Id 和 IdOperation。您希望创建项目组,其中每个组中的每个项目都具有相同的 IdOperation 值。您想通过 Id 升序对每个组中的元素进行排序,并创建一些匿名类型。

    你没有在你的匿名对象中指定你想要的东西(毕竟:你的代码没有做你想要的,所以我不能从你的代码中扣除它)

    每当我使用 GroupBy,并且我想指定每个组的元素时,我都会使用 overload of GroupBy that has a parameter resultSelector。使用 resultSelector 我可以精确地定义组的元素。 (链接指的是IQueryable,还有一个IEnumerable version

    IEnumerable<Operations> operations = ...      // = your list
    
    // Make Groups of Operations that have the same value for IdOperation
    var result = operations.GroupBy(operation => operation.IdOperation,
    
    // parameter resultSelector: take the key (=idOperation) and all Operations that have
    // this idOperation, to make one new.
    (idOperation, operationsWithThisId) => new
    {
        // do you need the common idOperation?
        IdOperation = idOperation,
    
        // Order the elements in each group by Id:
        Operations = operationsWithThisId.OrderBy(operation => operation.Id)
            .Select(operation => new
            {
                // Select only the operation properties that you plan to use
                Id = operation.Id,
                Name = operation.Name,
                StartDate = operation.StartDate,
                ...
            })
            .ToList(),
    });
    

    简而言之:从您的操作序列中,创建具有相同 IdOperation 值的操作组。然后使用这个通用的 IdOperation 以及该组中的所有操作来制作一个匿名对象:这就是您所说的匿名对象。因此,每个组,您制作一个匿名对象。

    • IdOperation 是该组中所有操作的共同值
    • 操作是一个列表。该组中的所有操作都按 Id 升序排列。选择了几个属性并将结果放入列表中。

    如果您想以不同方式分组,例如查询语法,只需更改参数 keySelector:

    var result = operations.GroupBy(operation => new
    { 
       Id = operation.ID,
       IdOperation = operation.IDOperation,
       IdDiagnosis = operation.IDDiagnosis
    },
    

    虽然这与您在查询语法中所做的相对应,但您将拥有一组具有相同 Id / IdOperation / IDDiagnosis 值的操作。按 Id 对组中的元素进行排序是没有用的,因为该组中的所有 Id 都将相等。

    结论
    使用参数 resultSelector,您可以完全按照自己的意愿定义结果:结果不是IEnumerable&lt;IGrouping&lt;Tkey, TElement&gt;&gt;,而是IEnumerable&lt;TResult&gt;

    TResult 是一个对象,由一组中的所有元素和公共组值创建。

    【讨论】:

      【解决方案2】:

      您可以更新 GetDict 函数内部循环以在组元素上使用 orderby

         public static void GetDict(List<Operation> list)
          {
              var res_g = (from dg in list
                           group new { dg.ID, dg.IDOperation, dg.IDDiagnosis } by dg.IDOperation
                   into dg_group 
                           select dg_group);
              foreach (var x in res_g)
              {
                  Console.WriteLine("Key: " + x.Key);
                  foreach (var y in x.OrderBy(o=>o.ID))
                  {
                      Console.WriteLine("{0} {1} {2}", y.ID, y.IDOperation, y.IDDiagnosis); ;
                  }
              }
          }
      

      我希望这能解决问题。

      根据您的要求编辑,但我正在调整结果集

                  var res_g_2 = list.Select( p=> new { p.ID, p.IDOperation, p.IDDiagnosis }) .GroupBy(g => g.IDOperation)
                                 .Select(g => new {
                                     IDOperation = g.Key,
                                     Records = g.OrderBy(group => group.ID)
                                 });
      

      编辑完整版

          public static void GetDict(List<Operation> list)
          {
              var res_g = (from dg in list
                           group new { dg.ID, dg.IDOperation, dg.IDDiagnosis } by dg.IDOperation
                   into dg_group
                           select new
                           {
                               Key = dg_group.Key,
                               Records = dg_group.OrderBy(g => g.ID)
                           }) ;
      
              var res_g_2 = list.Select( p=> new { p.ID, p.IDOperation, p.IDDiagnosis }) .GroupBy(g => g.IDOperation)
                                 .Select(g => new {
                                     Key = g.Key,
                                     Records = g.OrderBy(group => group.ID)
                                 });
      
              // you can use either res_g or res_g_2 both give the same results
              foreach (var x in res_g)
              {
                  Console.WriteLine("Key: " + x.Key);
                  foreach (var y in x.Records)
                  {
                      Console.WriteLine("{0} {1} {2}", y.ID, y.IDOperation, y.IDDiagnosis); ;
                  }
              }
          }
      

      【讨论】:

      • 谢谢。但我想修改 linq 查询。添加foreach循环只是为了写入结果。
      • 使用 group by 会使您失去对当前在上下文中的列表的控制,该列表仅包含新创建的组(键和组本身)允许您使用的所有操作 group.Key ,然后您可以维护对自己的组(IEnumerable)操作的操作。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-21
      • 2015-07-19
      相关资源
      最近更新 更多