web-dev-qa-db-fra.com

Comment utiliser LINQ pour sélectionner un objet?

J'ai des données qui ressemblent à ceci:

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

J'ai aussi le cours suivant:

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

Ce que je voudrais faire, c'est utiliser LINQ pour sélectionner dans mes données afin de créer une collection d'objets SongsForUser. Ci-dessous, ce que je suis arrivé jusqu'à présent:

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

Comment pourrais-je remplir ma liste Songs?

Le résultat devrait donc être deux objets SongsForUser. Pour l'utilisateur 1, il aurait 3 éléments dans la liste Songs. Pour l'utilisateur 2, il aurait 1 élément dans la liste Songs.

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

Je suppose que tu veux:

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

Pour expliquer, après la GroupBy, vous aurez un groupe de groupes, où la clé de chaque groupe est l’ID utilisateur et les valeurs du groupe sont les ID de morceaux:

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

Ensuite, vous ne faites que convertir cela en votre type SongsForUser. Notez que vous n'avez pas besoin d'inclure explicitement le () lorsque vous appelez le constructeur dans un initialiseur d'objet. C'est implicite, sauf si vous devez spécifier des arguments de constructeur.

Vous pourriez faire tout cela en un seul appel GroupBy, au fait:

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

Personnellement, je trouve généralement un appel Select séparé plus lisible.

Vous pouvez également faire tout cela avec une expression de requête:

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: Ce qui précède est "indépendant du fournisseur" mais il semble que cela ne fonctionne pas avec LINQ to Entities. Vous pouvez pouvoir le faire fonctionner comme ceci:

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

L'appel AsEnumerable obligera le regroupement à être effectué dans la base de données, mais la projection finale (y compris l'appel ToList) à être effectuée localement. Vous devriez cependant vérifier l'efficacité du code généré.

19
Jon Skeet

Dans sa forme la plus simple, vous pouvez simplement:

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();
0
pat capozzi

Disons que vous avez ce qui suit:

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

Ensuite, une fonction comme celle-ci fera l'affaire. La liste est juste là pour avoir Des données à tester.

    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 contient ensuite 2 éléments de type SongsForUser . Un avec l'utilisateur 1 et une liste de morceaux contenant 1, 4 et 12 , l'autre avec l'utilisateur 2 et une liste de morceaux contenant 95.

0
Mare Infinitus