TheWebGuy
TheWebGuy

Reputation: 12525

LINQ - Group By child property

I have a list of users, each user has string array property called Tags. I am trying to get a unique list of tags and a total count, any idea what I a missing here? I am using LinqPad to write my test query, please see the example code:

void Main()
{
    List<User> users = new List<User>(){
        new User {Id = 1, Tags = new string[]{"tag1", "tag2"}},
        new User {Id = 2, Tags = new string[]{"tag3", "tag7"}},
        new User {Id = 3, Tags = new string[]{"tag7", "tag8"}},
        new User {Id = 4, Tags = new string[]{"tag1", "tag4"}},
        new User {Id = 5 },
    };

    var uniqueTags = users.Where(m=>m.Tags != null).GroupBy(m=>m.Tags).Select(m=> new{TagName = m.Key, Count = m.Count()});
    uniqueTags.Dump();

    // RESULT should BE:
    // tag1 - Count(2)
    // tag2 - Count(1)
    // tag3 - Count(1)
    // tag4 - Count(1)
    // tag7 - Count(2)
    // tag8 - Count(1)
}

public class User{
    public int Id {get;set;}
    public string[] Tags {get;set;}
}

Upvotes: 0

Views: 16

Answers (1)

Slai
Slai

Reputation: 22866

You can flatten to IEnumerable<string> before grouping:

var uniqueTags = users.SelectMany(u => u.Tags ?? new string[0])
                      .GroupBy(t => t)
                      .Select(g => new { TagName = g.Key, Count = g.Count() } );

LINQPad C# Expression version:

new[] {
    new { Id = 1, Tags = new[] { "tag1", "tag2" } },
    new { Id = 2, Tags = new[] { "tag3", "tag7" } },
    new { Id = 3, Tags = new[] { "tag7", "tag8" } },
    new { Id = 4, Tags = new[] { "tag1", "tag4" } },
    new { Id = 5, Tags = (string[])null }
}
.SelectMany(u => u.Tags ?? Enumerable.Empty<string>())
.GroupBy(t => t)
.Select(g => new { TagName = g.Key, Count = g.Count() } )

Upvotes: 1

Related Questions