Search code examples
linqanonymous

How to order items within the group of anonymous type?


I would like to get a result of Linq query as groups of anonymous objects. The items within the groups should be ordered by ID field. I can reach this partly by lambda syntax, but can't get an anonymous objects as result. So I need part of each example. Executable code: 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 syntax

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

Solution

  • Alas, you didn't describe exactly your requirements where, only that you want some anonymous type and that they should be ordered by Id. Your query syntax makes different groups than your method syntax. So I can only give an example to create your sequence of anonymous objects

    So you have a sequence of similar items, where every item has at least properties Id and IdOperation. You want to make groups of items where every item in each group has the same value for IdOperation. You want to order the elements in each group by ascending Id, and create some anonymous type.

    You didn't specify what you want in your anonymous object (after all: your code doesn't do what you want, so I can't deduct it from your code)

    Whenever I use GroupBy, and I want to specify the elements of each group, I use the overload of GroupBy that has a parameter resultSelector. With the resultSelector I can precisely define the elements of the group. (The link refers to IQueryable, there is also an 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(),
    });
    

    In words: from your sequence of Operations, make groups of Operations that have the same value for IdOperation. Then take this common IdOperation, and all Operations that are in this group, to make one anonymous object: this is the anonymous object that you were talking about. So per group, you make one anonymous object.

    • IdOperation is the value that all Operations in this group have in common
    • Operations is a list. All Operations in this group are ordered by ascending Id. Several properties are Selected and the result is put in a List.

    If you want to group differently, like in you query syntax, simply change parameter keySelector:

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

    Although this corresponds with what you did in your query syntax, you will have groups of Operations that have same value for Id / IdOperation / IDDiagnosis. It will be useless to sort the elements in the group by Id, because all Ids in this group will be equal.

    Conclusion
    With parameter resultSelector you can define the result exactly as you want: the result is not an IEnumerable<IGrouping<Tkey, TElement>>, but an IEnumerable<TResult>.

    The TResult is one object created from all elements in one group and the common group value.