Nesnelerin bir listesini yeni gruplanmış nesne listesi halinde gruplamak için Linq kullanma


152

Linq'te bunun mümkün olup olmadığını bilmiyorum ama işte burada ...

Bir nesnem var:

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

Aşağıdakine benzeyen bir liste döndürüyorum:

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 } );

Yukarıdaki listede tüm kullanıcıları GroupID'ye göre gruplayan bir Linq sorgusu çalıştırabilmek istiyorum. Böylece çıktı, kullanıcıyı içeren kullanıcı listelerinin bir listesi olacaktır (eğer bu mantıklıysa?). Gibi bir şey:

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

Groupby linq cümlesini kullanmayı denedim, ancak bu bir anahtar listesi döndürüyor gibi görünüyor ve doğru şekilde gruplandırılmamış:

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

Yanıtlar:


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

1
çok güzel, tam da ihtiyacım olan şey. teşekkür ederim. bunu zorunlu yol yapmak berbat.
user1841243

1
İyi çalışıyor mu? çünkü bu yollar işe yaramadı. objModel.tblDonars.GroupBy (t => new {t.CreatedOn.Year, t.CreatedOn.Month, t.CreatedOn.Day}). (g => new {tblDonar = g.ToList ()}) öğesini seçin. ToList ( ); bu işe yaramıyor ... yardım edebilir misin ....
Rajamohan Anguchamy

Çözümünüzle iyi çalışıyor ancak grupta 8 değere kadar bir sorum var ve her grupta sadece 6 çekimle ihtiyacım var, bu yüzden bunu nasıl yapabilirim lütfen bana bildirin.
coderwill

GroupID'ye göre gruplandırdıktan sonra Kullanıcı Adlarını ve Kullanıcı Kimliklerini ayrı ayrı listelemenin bir yolu var mı? groupID 1 için - {"1", [1, 2, 4], ["UserOne", "UserTwo", "UserFour"]} gibi
Ajay

2
Şu anda kod çalışmıyor ve önceki liste türüne dönüştürmeye çalıştığınızda bir hataya neden oluyor. Çünkü select'te bir Liste döndürmek, burada istenen çıktı olmayan bir liste içinde Listeler oluşturur. Sorun yaşayanlar için şunları önerebilirim: var groupedCustomerList = userList.GroupBy (u => u.GroupID). (Grp => grp.First ()). ToList ();
aliassce

37

Grubunuz deyimi irade grup kimliğine göre grup. Örneğin, o zaman şunu yazarsan:

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

bu iyi çalışmalı. Her grup vardır bir anahtar, aynı zamanda içerdiği IGrouping<TKey, TElement>Eğer grubun üyelerini üzerinde yineleme sağlayan bir koleksiyon olan. Lee'nin bahsettiği gibi, gerçekten isterseniz her grubu bir listeye dönüştürebilirsiniz, ancak yukarıdaki koda göre bunları yinelerseniz, bunu yapmanın gerçek bir faydası yoktur.


4

Tip için

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

Toplamak

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" }
};

linq sorgumuz aşağıdaki gibi görünüyor

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

veya aşağıdaki gibi liste yerine dizi için

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

Hala eski bir soru, ancak Lee'nin cevabı bana grubu vermedi. Sonuç olarak anahtar. Bu nedenle, bir listeyi gruplandırmak ve gruplanmış bir listeyi döndürmek için aşağıdaki ifadeyi kullanıyorum:

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

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

Her grubun artık bir anahtarı vardır, ancak aynı zamanda grubun üyeleri üzerinde yineleme yapmanızı sağlayan bir koleksiyon olan bir IGrouping içerir.


Bu , OP'nin sorusunu değil , sorunuzu yanıtlar . Sadece liste listesi istiyorlar. Kodunuz bunu sağlamaz.
Gert Arnold

Bu çözümü gönderdiniz çünkü yok gibi @Lee zaman iterating çalışmaz yukarıda kabul cevap değil sağlamak group.key@JohnSkeet tarafından cevap gösterilen gibi zaman iterating gruplandırılmış listesi üzerinden eleman. Verdiğim yanıt , yineleme sırasında group.key öğesini sağlıyor. Bu nedenle, verilen cevapların yukarıda gösterildiği gibi çalışmaması tuzağına düşen diğerlerine yardımcı olabilir. Dolayısıyla, kabul edilen yanıta benzer group.key öğesini elde etmenin avantajıyla listeyi elde etmenin başka bir yoludur. İddianızı anlamayın @GertArnold. (.net çekirdek 3.0)
veri havuzu

Bence tüm soru ne IGroupingolduğunu anlamamaktan kaynaklanıyor . Bu nedenle OP , kodunuzla özdeş olan kendi doğru kodunu alttan atar . Bu yüzden tam olarak istediklerini sağlayan bir cevabı kabul ederler. İhtiyaç duydukları şey, JS'nin yeterince sağladığı bir açıklamadır.
Gert Arnold
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.