Reynevan
Reynevan

Reputation: 1545

Group elements by an array/Collection<T>

Let's say I have a Track class that has a string[] Genres property.

How can I efficiently group Track elements into genres with one entry being a part of multiple groups if needed? For example, for following collection:

A - Rock
B - Pop, Rock
C - Rock, Soundtrack
D - Pop, Soundtrack

The result for this should be:

Rock - A, B, C
Pop - B, D
Soundtrack - C, D

Is there any easy way to do that using LINQ? Or is there a more efficient way than using LINQ alltogether?

Thanks!

Upvotes: 0

Views: 650

Answers (1)

Christos
Christos

Reputation: 53958

You could try something like this:

var genresTracks = tracks.SelectMany(track => track.Genres, (track, genre) => new 
                         { 
                             // you might want to correct the Name property
                             // with the correct one.
                             Track = track.Name, 
                             Genre = genre
                         })
                         .GroupBy(tg => tg.Genre)
                         .Select(gr => new 
                         {
                             Genre = gr.Key, 
                             Tracks = gr.Select(x=>x.Track)
                         });

foreach(var genreTracks in genresTracks)
{
    var tracksCsv = string.Join(",", genreTracks.Tracks);
    Console.WriteLine($"{genreTracks.Genre} - {tracksCsv}");
}

Initially we flatten our collection using the SelectMany method, to a sequence of anonymous objects with two properties, Track - the track's name and Genre - one of the genres, in which this track can be categorized to. So the newly sequence would pe consisted of pairs like ("A","Rock"), ("B","Rock"), ("B","Pop"), etc. Then we GroupBy this sequence based on the Genre property, so groups are created with key the Genre and Members the track names. Last we project each group into an object with two properties the Genre and the Tracks.

Upvotes: 4

Related Questions