2012-07-19 18 views
22

私はそうのように見えるのデータている:私は何をしたいことのコレクションを作成するために、私のデータから選択するために、LINQを使用しているLINQを使ってオブジェクトを選択するには?

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

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

は、私はまた、次のクラスを持っていますSongsForUserオブジェクト。以下は、私がこれまでに出ているものです:

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

は、どのように私は私のSongsリストを取り込むに行きますか?

したがって、結果は2つのSongsForUserオブジェクトである必要があります。ユーザー1の場合、Songsリストに3つの項目が含まれます。ユーザー2の場合、Songsリストに1つの項目が含まれます。私はあなたを疑う

答えて

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

ソングIDはグループ化の一部ではなく、投影内でのみ選択するのはなぜですか? –

+1

これは 'ToList'部分にエラーを投げています。私はこれがエンティティへのLinqであるかもしれないと信じています。エラー: 'LINQ to Entitiesは、 'System.Collections.Generic.List'1 [System.String] ToList [String](System.Collections.Generic.IEnumerable'1 [System.String])メソッドを認識しません。このメソッドをストア式に変換することはできません。 ' –

+0

@AbeMiesslerは、 'using System.Linq'を上にしてください。 –

19

が欲しい:GroupByあなたは、各グループのキーはユーザーIDであるグループ、の束を持っています後、

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

を説明するために、そして内の値グループは、歌のIDがされています。そして、あなたは自分のSongsForUser型にそれを変換している

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

。オブジェクトイニシャライザでコンストラクタを呼び出すときに、()を明示的にインクルードする必要はありません。コンストラクタの引数を指定する必要がない限り暗黙的です。

あなたが方法により、全て1回のGroupBy呼び出しでこれを行うことができます:

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

は個人的に私は通常、読みやすくするために、別の Selectコールを見つけます。

また、クエリ式でこのすべてを行うことができます。

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:上記は「プロバイダ中立」であるが、それはエンティティへのLINQで動作していないているように聞こえます。あなたそれがこのように動作するように取得することができる場合があります

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

AsEnumerable呼び出しは、データベースに行われるグループ化を強制しますが、(ToListコールを含む)は、最終的な投影がローカルで行われます。しかし、効率のために生成されたSQLをチェックする必要があります。

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

そこでここでは、このような関数が行います。

0

では、次のしているとしましょう。リストには、テストするデータが あることがあります。

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は、後でタイプ2のSongsForUserを含みます。 1のユーザーと1、4、12の曲のリスト と1のユーザー2と95を含む曲のリスト

関連する問題