Sunil Kumar
Sunil Kumar

Reputation: 3242

Group by on string Array in List of items c#

I have a List of BlogPageModel , in List I have string Array of Category.

Model class looks like below:

    public class BlogPageModel : BaseModel
    {
        public string Title { get; set; }
        public string Slug { get; set; }
        public string[] Category { get; set; }
    }

I want list of all Category with blogs count as output, i.e

Travel-20
Entertainment-5

Note: Travel-20 mean 20 blogs are in list which have Travel Category, and Entertainment-5 mean 5 blogs are Entertainment category, remember few blogs have both categories.

I tried to apply GroupBy like below:

_client.GetRecords().Result.GroupBy(x => x.Category).Select(x => new { Key = x.Key })

But it's not working and returning list of blogs.

I also tried below:

enter image description here

I am not sure what I am doing wrong in my query.

Upvotes: 1

Views: 634

Answers (2)

Caius Jard
Caius Jard

Reputation: 74605

You can expand the blogs with their list of categories to a new sequence of just the category, before you group it:

_client.GetRecords().Result.SelectMany(blog => blog.Category).GroupBy(x => x.Category).Select(x => x.Key + "-" + x.Count());

x is an IGrouping, basically like a List together with a Key. You can do things on it that you would do on a List, like Count or First. Every item in the list has a common Key, which was chosen as part of the GroupBy. In this case your x where the key is "Travel" is a list of Category 20 long

Incidentally, (assuming GetRecords returns a Task) consider whether you should be using .Result - it blocks the calling thread until the operation is finished which is a great way to nuke all the advantages of task based Async pattern and revert to synchronous code. If you instead await GetRecords (which should be called GetRecordsAsync) then it will free the thread up to go and do other things while the records are being returned

(await _client.GetRecords()).SelectMany(blog => blog.Category).GroupBy(x => x.Category).Select(x => x.Key + "-" + x.Count());

If you want to keep the Blog object after the SelectMany has ended you can use:

(await _client.GetRecords()).SelectMany(b => blog.Category, (b, c) => new { Blog = blog, Cat = c })

You'll get an enumerable that has Nblogs * Ncategories (25 items)

Upvotes: 2

Hadi Samadzad
Hadi Samadzad

Reputation: 1540

Firstly flatten the result using SelectMany. You should use GroupBy Again to grouping the tags by key and finally count them like this:

var result = _client.GetRecords().Result
                .SelectMany(x => x.Category)
                .GroupBy(x => x)
                .Select(x => $"{x.Key}-{x.Count()}");

Upvotes: 2

Related Questions