cAMPy
cAMPy

Reputation: 587

C# LINQ Select objects with the same value of one property join values of other

I have a list of prods like this:

Prod1: Id=1, Name="name1", Color="Blue"
Prod2: Id=1, Name="name1", Color="Green"
Prod3: Id=2, Name="Test2, Color="Red"

What I want to perform is to get reduced list like this:

Prod1: Id=1, Name="name1", Color="Blue, Green"
Prod3: Id=2, Name="Test2, Color="Red"

I always want to take prods with the same id and add up their colors. I feel there is a clever one code line way to do this, but I somehow got stuck with:

productList.GroupBy(p => new { p.Id }).Select(x => x.First()).ToList();

which does not give me an ability to add second color. Will apreciate any help

Upvotes: 6

Views: 11197

Answers (2)

amavroudakis
amavroudakis

Reputation: 2362

An alternative would be to try to edit the first instance of each product in the products list to add all colors from all instances without creating a new anonymous type to hold the data (as per the accepted answer).

Complete code:

public class Program
{
    public static void Main()
    {
        List<Product> products = new List<Product>
        {
            new Product() {Id = 1, Name="name1", Color="Blue"},
            new Product() {Id = 1, Name="name1", Color="Green"},
            new Product() {Id = 1, Name="name1", Color="Green"},
            new Product() {Id = 2, Name="name2", Color="Red"}
        };
                                 
        var results = from product in products
            group product by product.Id into g // there is no need to group by a complex key if product.Id is unique per product
            let colors = string.Join(",", g.Select(c=> c.Color).Distinct()) 
            let p = g.First().Color = colors
            select g.First();
                        
        foreach(var result in results)
            Console.WriteLine(result);          
    }
}

public class Product
{
    public int Id;
    public string Name;
    public string Color;
    
    public override string ToString()
    {
        return string.Format("Id:\"{0}\", Name:\"{1}\", Color:\"{2}\"", Id, Name, Color);
    }
}

This will change in place the value of the "Color" property of the first instance of product with id=1 discarding any other instances in the list.

It will print:

Id:"1", Name:"name1", Color:"blue,Green"
Id:"2", Name:"name2", Color:"Red"

Working code: https://dotnetfiddle.net/HLtHIE

I am not claiming that this is better or more efficient, but it is worthy alternative.

Upvotes: 0

Hari Prasad
Hari Prasad

Reputation: 16956

Try this.

productList.GroupBy(p => new { p.Id, p.Name })
           .Select(x =>new {
                      Id =x.Key.Id, 
                      Name = x.Key.Name,
                      Color = String.Join(",", x.Select(c=> c.Color)) 
               }); 

Working Demo

Upvotes: 16

Related Questions