JL.
JL.

Reputation: 81342

C# Linq convert collection using groupby

I have a list of a class that looks like this

public class MyClass
{
   public ComplexType A {get;set;}
   public ComplexTypeB B {get;set;}
}

var myList = new List<MyClass>();

I then have a target Dto which looks like this

public class MyTargetDto
{
    public ComplexType A {get;set;}
    public List<ComplexTypeB> ListOfB {get;set;}
}

It's very similar only that myTargetDto supports grouping by ComplexType

Given a flat list of MyClass, how can I (using Linq) convert it to a target list of MyTargetDto?

Upvotes: 0

Views: 122

Answers (4)

Arthur Rey
Arthur Rey

Reputation: 3056

As already posted by others, a solution would be

myList.GroupBy(x => x.A, x => x.B)
      .Select(g => new MyTargetDto()
      {
          A = g.Key,
          ListOfB = g.ToList()
      });

Just wanted you to see an existing shortcut using a GroupBy overload

myList.GroupBy(x => x.A, x => x.B, (key, g) => new MyTargetDto()
{
    A = key,
    ListOfB = g.ToList()
}); 

Upvotes: 0

Gilad Green
Gilad Green

Reputation: 37271

myList.GroupBy(item => item.A)
    .Select(group => new MyTargetDto
    {
        A = group.Key,
        ListOfB = group.Select(item => item.B).ToList()
    });

Upvotes: 0

Ren&#233; Vogt
Ren&#233; Vogt

Reputation: 43906

If your ComplexType does not have an own implementation of Equals than at first you would need to implement an IEqualityComparer<ComplexType>:

public class Comparer : IEqualityComparer<ComplexType>
{
    public bool Equals(ComplexType x, ComplexType y)
    {
        // code to check your complex type for equality
    }
    public int GetHashCode(ComplexType obj)
    {
        return obj.GetHashCode();
    }
}

Then you can use this comparer to group your list using GroupBy:

List<MyClass> flatList = ...
List<MyTargetDto> result = flatList.GroupBy(e => e.A, e => e.B, new Comparer())
                                   .Select(g => new MyTargetDto {
                                         A = g.Key,
                                         ListOfB = g.ToList()});
                                    .ToList();

If ComplexType already has an own implementation of Equals that works appropriatly, than you can ommit that comparer:

List<MyTargetDto> result = flatList.GroupBy(e => e.A, e => e.B)
                                   .Select(g => new MyTargetDto {
                                         A = g.Key,
                                         ListOfB = g.ToList()})
                                    .ToList();

The first lambda of GroupBy selects the element by which the list is grouped. This will then be the Key property in the resulting IGrouping.
The second lambda selects the elements that should be contained in that group.

The final Select creates for each group a MyTargetDto, setting it's A property to the ComplexType and creating the ListOfB.

Upvotes: 0

Hari Prasad
Hari Prasad

Reputation: 16966

You should do something like this.

myList.GroupBy(x=>x.A)
      .Select(x=> new MyTargetDto()
       {
           A= x.Key,
           ListOfB = x.Select(s=>s.B).ToList()
       });

Upvotes: 1

Related Questions