Menggunakan Linq untuk mengelompokkan daftar objek ke daftar daftar objek yang dikelompokkan


149

Saya tidak tahu apakah ini mungkin di Linq tapi begini ...

Saya punya objek:

public class User
{
  public int UserID { get; set; }
  public string UserName { get; set; }
  public int GroupID { get; set; }
}

Saya mengembalikan daftar yang mungkin terlihat seperti berikut:

List<User> userList = new List<User>();
userList.Add( new User { UserID = 1, UserName = "UserOne", GroupID = 1 } );
userList.Add( new User { UserID = 2, UserName = "UserTwo", GroupID = 1 } );
userList.Add( new User { UserID = 3, UserName = "UserThree", GroupID = 2 } );
userList.Add( new User { UserID = 4, UserName = "UserFour", GroupID = 1 } );
userList.Add( new User { UserID = 5, UserName = "UserFive", GroupID = 3 } );
userList.Add( new User { UserID = 6, UserName = "UserSix", GroupID = 3 } );

Saya ingin dapat menjalankan kueri Linq pada daftar di atas yang mengelompokkan semua pengguna berdasarkan GroupID. Jadi output akan menjadi daftar daftar pengguna yang berisi pengguna (jika itu masuk akal?). Sesuatu seperti:

GroupedUserList
    UserList
        UserID = 1, UserName = "UserOne", GroupID = 1
        UserID = 2, UserName = "UserTwo", GroupID = 1
        UserID = 4, UserName = "UserFour", GroupID = 1
    UserList
        UserID = 3, UserName = "UserThree", GroupID = 2
    UserList
        UserID = 5, UserName = "UserFive", GroupID = 3
        UserID = 6, UserName = "UserSix", GroupID = 3

Saya sudah mencoba menggunakan klausa groupby linq tetapi ini sepertinya mengembalikan daftar kunci dan tidak dikelompokkan dengan benar:

var groupedCustomerList = userList.GroupBy( u => u.GroupID ).ToList();

Jawaban:


309
var groupedCustomerList = userList
    .GroupBy(u => u.GroupID)
    .Select(grp => grp.ToList())
    .ToList();

1
sangat bagus, hanya apa yang saya butuhkan. Terima kasih. melakukan ini dengan cara imperatif menyebalkan.
user1841243

1
Apakah ini berfungsi dengan baik? karena saya terbiasa cara ini tidak berhasil. objModel.tblDonars.GroupBy (t => new {t.CreatedOn.Year, t.CreatedOn.Month, t.CreatedOn.Day}). Pilih (g => new {tblDonar = g.ToList ()}) .Daftar ( ); ini tidak berfungsi ... dapatkah Anda membantu ....
Rajamohan Anguchamy

dengan solusi Anda itu berfungsi dengan baik tetapi saya punya satu pertanyaan kira dalam kelompok hingga nilai 8 dan saya ingin hanya perlu dalam setiap grup dengan hanya 6 take jadi bagaimana bisa melakukan itu tolong beri tahu saya.
coderwill

apakah ada cara untuk mencantumkan UserNames dan UserID secara terpisah setelah dikelompokkan berdasarkan GroupID? seperti - {"1", [1, 2, 4], ["UserOne", "UserTwo", "UserFour"]} untuk groupID 1.
Ajay Aradhya

1
Saat ini kode tidak berfungsi dan menyebabkan kesalahan jika Anda mencoba melemparkannya ke daftar jenis sebelumnya. Karena mengembalikan Daftar di pilih membuat Daftar di dalam daftar yang bukan hasil yang diinginkan di sini. Bagi mereka yang memiliki masalah saya dapat menyarankan: var groupedCustomerList = userList.GroupBy (u => u.GroupID). Pilih (grp => grp.First ()). ToList ();
aliassce

36

Pernyataan grup Anda akan dikelompokkan berdasarkan ID grup. Misalnya, jika Anda kemudian menulis:

foreach (var group in groupedCustomerList)
{
    Console.WriteLine("Group {0}", group.Key);
    foreach (var user in group)
    {
        Console.WriteLine("  {0}", user.UserName);
    }
}

itu seharusnya bekerja dengan baik. Setiap grup memiliki kunci, tetapi juga berisi IGrouping<TKey, TElement>yang merupakan koleksi yang memungkinkan Anda untuk beralih dari anggota grup. Seperti yang disebutkan Lee, Anda dapat mengonversikan setiap grup ke daftar jika Anda benar-benar ingin, tetapi jika Anda hanya akan mengulanginya sesuai kode di atas, tidak ada manfaat nyata untuk melakukannya.


4

Untuk tipe

public class KeyValue
{
    public string KeyCol { get; set; }
    public string ValueCol { get; set; }
}

koleksi

var wordList = new Model.DTO.KeyValue[] {
    new Model.DTO.KeyValue {KeyCol="key1", ValueCol="value1" },
    new Model.DTO.KeyValue {KeyCol="key2", ValueCol="value1" },
    new Model.DTO.KeyValue {KeyCol="key3", ValueCol="value2" },
    new Model.DTO.KeyValue {KeyCol="key4", ValueCol="value2" },
    new Model.DTO.KeyValue {KeyCol="key5", ValueCol="value3" },
    new Model.DTO.KeyValue {KeyCol="key6", ValueCol="value4" }
};

permintaan LINQ kami terlihat seperti di bawah ini

var query =from m in wordList group m.KeyCol by m.ValueCol into g
select new { Name = g.Key, KeyCols = g.ToList() };

atau untuk array bukan daftar seperti di bawah ini

var query =from m in wordList group m.KeyCol by m.ValueCol into g
select new { Name = g.Key, KeyCols = g.ToList().ToArray<string>() };

-1

Masih yang lama, tetapi jawaban dari Lee tidak memberi saya grup. Oleh karena itu, saya menggunakan pernyataan berikut untuk mengelompokkan daftar dan mengembalikan daftar yang dikelompokkan:

public IOrderedEnumerable<IGrouping<string, User>> groupedCustomerList;

groupedCustomerList =
        from User in userList
        group User by User.GroupID into newGroup
        orderby newGroup.Key
        select newGroup;

Setiap grup sekarang memiliki kunci, tetapi juga berisi IGrouping yang merupakan koleksi yang memungkinkan Anda untuk beralih ke anggota grup.


Ini menjawab pertanyaan Anda , bukan pertanyaan OP. Mereka hanya menginginkan daftar daftar. Kode Anda tidak menyediakan itu.
Gert Arnold

Saya telah memposting solusi ini karena jawaban yang diterima di atas dari @Lee tidak berfungsi saat iterasi karena tidak memberikan group.keyelemen ketika iterasi melalui daftar yang dikelompokkan seperti ditunjukkan dalam jawaban oleh @JohnSkeet. Jawaban saya yang disediakan memang menyediakan elemen group.key saat iterasi. Jadi mungkin membantu orang lain jatuh ke dalam perangkap bahwa jawaban yang diberikan tidak berfungsi seperti yang ditunjukkan di atas. Jadi itu hanyalah cara lain untuk mendapatkan daftar dengan manfaat mendapatkan elemen group.key mirip dengan jawaban yang diterima. Jangan mengerti klaim Anda @GertArnold. (.net core 3.0)
datapool

Saya pikir seluruh pertanyaan didasarkan pada kurangnya pemahaman tentang apa IGroupingitu. Itu sebabnya OP membuang kode mereka sendiri di bagian bawah, yang pada dasarnya identik dengan kode Anda. Itu sebabnya mereka menerima jawaban yang memberikan apa yang mereka minta. Yang mereka butuhkan adalah penjelasan, yang disediakan JS dengan cukup.
Gert Arnold
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.