Jairo
Jairo

Reputation: 426

Nested IGrouping with LinQ

I want to know if it's possible to get a List<IGrouping<string, IGrouping<string, T>>> out of a Linq expression. What I want to do is order songs by genre and artist, but in a format where I can iterate through each genre and for every genre, iterate for each album. If it's possible how can it be done? Or is there a better approach to what I want to achieve?

Here's my Song class

public class Song
{
    [StringLength(100)]
    public string Album { get; set; }

    public int Id { get; set; }

    [StringLength(100)]
    public string Title { get; set; }

    [StringLength(100)]
    public string Genre { get; set; }

    [StringLength(255)]
    public string Comment { get; set; }

    [StringLength(4)]
    public string Year { get; set; }

    [StringLength(100)]
    public string Author { get; set; }

    public int Length { get; set; }

    [StringLength(255)]
    public string Photo { get; set; }

    [StringLength(255)]
    public string FileName { get; set; }

    public string Extension { get; set; }
}

And this query I had here

var songs = db.Songs.GroupBy(s => s.Genre).ToList();

gives me a List<IGrouping<string, Song>> but what I want is to further group by Artist.

Upvotes: 2

Views: 903

Answers (3)

Jairo
Jairo

Reputation: 426

What I wanted was a List<IGrouping<string, IGrouping<string, Song>>> and this code gives me exactly what I want

            var queryNestedGroups =
            (from song in db.Songs
            group song by song.Genre into newGroup1
            from newGroup2 in
                (from song in newGroup1
                 group song by song.Author)
            group newGroup2 by newGroup1.Key).ToList();

(though I'm not quite sure how to translate it into linq method syntax).

Thanks to everyone who commented and/or answered.

Upvotes: 6

user5606561
user5606561

Reputation: 139

Try adding a second grouping to the results of the first

var songs = db.Songs.GroupBy(s => s.Artist).SelectMany(s => s.GroupBy (d =>  d.Genre)).OrderBy (s => s.Key).ToList();

Upvotes: -1

jamespconnor
jamespconnor

Reputation: 1422

var songs = db.Songs.GroupBy(s => s.Genre, (genre, genreGroup) => new 
                                    { 
                                       Genre = genre, 
                                       ArtistGroup = genreGroup.GroupBy(s => s.Artist)
                                    });

This will return almost what you want, however IGrouping<string, IGrouping<string, Song>> can only be returned if you implement IGrouping<K,V> with your own class and new that up instead of the anonymous type I used above.

Upvotes: 2

Related Questions