How to use LINQ to select into an object?

本秂侑毒 提交于 2020-01-01 07:28:06

问题


I have data that looks like so:

UserId   |  SongId
--------   --------
1          1
1          4
1          12
2          95

I also have the following class:

class SongsForUser
{
    public int User;
    public List<int> Songs;
}

What I would like to do is use LINQ to select from my data to create a collection of SongsForUser objects. Below is what I have come up with so far:

var userCombos = songs.UserSongs.Select(x => new SongsForUser() { User = x.UserId, 
                                                                  Songs = /*What goes here?*/ });

How would I go about populating my Songs List?

So the result should be two SongsForUser objects. For user 1 it would have 3 items in the Songs list. For user 2 it would have 1 item in the Songs list.


回答1:


songs.UserSongs.GroupBy(x => x.User).Select(g => new SongsForUser() 
{ 
    User = g.Key,
    Songs = g.Select(s => s.SongId).ToList()
});



回答2:


I suspect you want:

var songsByUser = songs.UserSongs
                       .GroupBy(song => song.UserId, song => song.SongId)
                       .Select(g => new SongsForUser { User = g.Key,
                                                       Songs = g.ToList() });

To explain, after the GroupBy you'll have a bunch of groups, where the key of each group is the user ID, and the values within the group are the song IDs:

Key = 1, Values = 1, 4, 12
Key = 2, Value = 95

Then you're just converting that into your SongsForUser type. Note that you don't need to explicitly include the () when calling the constructor in an object initializer - it's implicit unless you need to specify constructor arguments.

You could do this all in one GroupBy call, by the way:

var songsByUser = songs.UserSongs
         .GroupBy(song => song.UserId, song => song.SongId,
                  (user, ids) => new SongsForUser { User = user,
                                                    Songs = ids.ToList() });

Personally I usually find a separate Select call to be more readable.

You can also do all of this with a query expression:

var songsByUser = from song in songs.UserSongs
                  group song.SongId by song.UserId into g
                  select new SongsForUser { User = g.Key, Songs = g.ToList() };

EDIT: The above is "provider-neutral" but it sounds like it's not working with LINQ to Entities. You may be able to get it to work like this:

var songsByUser = songs.UserSongs
                       .GroupBy(song => song.UserId, song => song.SongId)
                       .AsEnumerable()
                       .Select(g => new SongsForUser { User = g.Key,
                                                       Songs = g.ToList() });

The AsEnumerable call will force the grouping to be done in the database, but the final projection (including the ToList call) to be done locally. You should check the generated SQL for efficiency though.




回答3:


Lets say you have the following:

public class SongsForUser
{
    public int UserId;
    public List<int> Songs;
}

Then a function like this one here will do. The list is just there to have some data to test with.

    public void Group()
    {
        List<Tuple<int, int>> SongRelations = new List<Tuple<int, int>>();

        SongRelations.Add(new Tuple<int, int>(1, 1));
        SongRelations.Add(new Tuple<int, int>(1, 4));
        SongRelations.Add(new Tuple<int, int>(1, 12));
        SongRelations.Add(new Tuple<int, int>(2, 95));

        var list = SongRelations.GroupBy(s => s.Item1)
                                .Select(r => new SongsForUser()
                                {
                                    UserId = r.Key,
                                    Songs = r.Select(t => t.Item2).ToList(),
                                });
    }

list contains 2 items of type SongsForUser afterwards. One with user 1 and a list of songs containing 1, 4 and 12 and one with user 2 and a list of songs containing 95.




回答4:


In its simplest form you can just:

List<MapPoint> points = db.PropertyResearches.Where(a => a.deptId == 66).Select(x => new MapPoint { property = x.notes.Substring(0, 10), latitude = x.lat, longitude = x.@long }).ToList();


来源:https://stackoverflow.com/questions/11554414/how-to-use-linq-to-select-into-an-object

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!