Reputation: 196
I have a list of products and every product have a string filed that is contain a list of tags that are concate with "#" character like this:
Tag1#Tage2#Tag3
I need to get all tags and order them by their number of their repeats.
I actually did this like this:
List<string> t = new List<string>();
var tags = (from p in db.Products
where p.Active
select p.Tags
).ToList();
foreach (var item in tags)
{
if (item == null)
continue;
var d = item.Split('#');
foreach (var item2 in d)
{
t.Add(item2);
}
}
var ans = t.GroupBy(p => new { id = p }).Select(g => new { id = g.Key.id, total = g.Count() }).OrderByDescending(g => g.total).ToList();
but im sure its not simple (and maybe optimized). Can someone help me to make this code simpler and better? for example with Linq statement etc..
Upvotes: 0
Views: 63
Reputation: 1734
Here's my variant:
using System;
using System.Linq;
namespace TagsSplitExample
{
public class Product
{
public bool Active { get; set; }
public string Tags { get; set; }
}
class Program
{
static void Main(string[] args)
{
var products = new[]
{
new Product{ Active = true, Tags = "Tag1"},
new Product{ Active = true, Tags = "Tag1#Tag2"},
new Product{ Active = true, Tags = "Tag1#Tag2#Tag3"},
};
var allTags = products
.Where(p => p.Active && p.Tags != null)
.Select(p => p.Tags)
.Select(tags => tags.Split('#'))
.SelectMany(tag => tag)
.GroupBy(tag => tag)
.Select(group => new { Tag = group.Key, Count = group.Count() })
.OrderByDescending(pair => pair.Count)
.ToList();
allTags.ForEach(pair => Console.WriteLine($"{pair.Tag} : {pair.Count}"));
Console.ReadLine();
}
}
}
Final ToList() can be omitted if you just need to enumerate result.
Result:
Tag1 : 3
Tag2 : 2
Tag3 : 1
Upvotes: 2