Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Group by Distinct using Linq

I want to distinctly merge two or more collections on an id and create a collection of the other property for each id.

I have an object foo

public class foo
{
    public int id { get; set; }
    public string color { get; set; }
}

Which I have multiple List<foo> which have common id's but with different colors

//list 1
id = 1, color = "red"
id = 2, color = "blue"
id = 3, color = "green"
id = 1, color = "blue"
id = 2, color = "orange"
//list 2                
id = 1, color = "black"
id = 2, color = "amber"
id = 3, color = "red"
id = 4, color = "red"
id = 2, color = "silver"

I want to use linq to project a new collection that will be distinct on the id but create and list of the color property.

id = 1, color = { "red", "blue", "black" }
id = 2, color = { "blue", "orange", "amber", "silver" }
id = 3, color = { "green", "red" }
id = 4, color = { "red" }

Q: How can this be written in linq

like image 295
ojhawkins Avatar asked Dec 25 '22 07:12

ojhawkins


2 Answers

var colours = list.GroupBy(x => x.id)
                  .Select(x => new {id = x.Key, color = x.Select(y => y.color).ToList()})
                  .ToList();

That will give you a list called colours in the structure you want.

If you want the colour field to be a comma separated string then change it to:

var colours = list.GroupBy(x => x.id)
                  .Select(x => new {id = x.Key, color = x.Select(y => y.color).ToArray().Join(",")})
                  .ToList();
like image 60
Kevin Holditch Avatar answered Dec 28 '22 06:12

Kevin Holditch


I think you want a Dictionary<int, List<string>> instead:

Dictionary<int, List<string>> idColors = foos
    .GroupBy(f => f.id)
    .ToDictionary(g => g.Key, g => g.Select(f => f.color).ToList());

Now you can access every id's color(s) in this way:

List<string> colors = idColors[1];
Console.WriteLine(string.Join(",", colors));
like image 29
Tim Schmelter Avatar answered Dec 28 '22 07:12

Tim Schmelter