问题描述:

I have a model like this:

public class Post

{

public int PostId,

public List<Category> Categories

}

Posts have at least 1 category, but can also have many categories.

I have a List, this list contains Posts (some with the same PostId), and each entry in the List contains exactly one unique Category (Categories.Count = 1 for each).

I want to create a new List with only distinct Posts (distinct PostId), with the Categories list populated with each category in the original List having the same PostId.

Basically, find each Post in the original list, and populate the Categories field by adding each of their First (and only) entry in their Categories field together.

Is there a nice solution for this in linq?

Category is just an Enum,

I have tried using varous nested foreach and for loops and it works but it is just gross. I know there is a clean way to do it.

Example:

Categories = { PostId = 1, Category = Shopping }, { PostId = 1, Category = Pizza }, { PostId = 2, Category = Laundry }

after sequence desired output to be:

Categories = { PostId = 1, Categories = Shopping, Pizza }, { PostId = 2, Categories = Laundry }

Order does not matter for the category list

网友答案:

Given that you will have only one category per post (as stated in the second paragraph), you can try

var result = aPosts
    .GroupBy(item => item.PostId, item => item.Categories[0])
    .Select(group => new Post() { PostId = group.Key, Categories = new List<Category>(group) })
    .ToList();

Note that having a Post constructor that accepts both PostId and Categories would allow a more simplified version of any solution.

Post(int postId, IEnumerable<Category> categories)
{
    PostId = postId;
    Categories = new List<Category>(categories);
}

Would allow the following:

var result = aPosts
    .GroupBy(item => item.PostId, item => item.Categories[0])
    .Select(group => new Post(group.Key, group))
    .ToList();
网友答案:

something like below

var result = yourlist.GroupBy(l=>l.PostId)
               .Select(x=>new Post{ PostId =x.Key, Categories =x.SelectMany(y=>y.Categories).ToList()})
               .ToList();
网友答案:

With LINQ expressions:

var result = from o in posts
group o by o.PostID into gr
select new Post
{
    PostID = gr.Key,
    Categories = gr.SelectMany(c=>c.Categories).ToList()
};
网友答案:

All the other given solutions would work. But if you might have more than 1 category in the Category list, and you need only the first of each Post you can use following.

var posts =
                postList.GroupBy(p => p.PostId)
                        .Select(
                            g =>
                            new Post
                                {
                                    PostId = g.Key,
                                    Categories =
                                        g.Select(p => p.Categories.FirstOrDefault())
                                        .Where(c => c != null).ToList()
                                });

Also, make sure you initialize you Categories property (e.g. in the constructor of Post class) before using Linq given in the answers. Otherwise you might get NUllReferenceException.

相关阅读:
Top