web-dev-qa-db-fra.com

Utilisation de Linq pour regrouper une liste d'objets dans une nouvelle liste groupée de liste d'objets

Je ne sais pas si c'est possible à Linq mais voilà ...

J'ai un objet:

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

Je retourne une liste qui peut ressembler à ceci:

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

Je veux pouvoir exécuter une requête Linq sur la liste ci-dessus qui regroupe tous les utilisateurs par GroupID. Donc, le résultat sera une liste de listes d'utilisateurs contenant l'utilisateur (si cela a du sens?). Quelque chose comme:

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

J'ai essayé d'utiliser la clause groupby linq mais celle-ci semble renvoyer une liste de clés et elle n'est pas groupée correctement:

var groupedCustomerList = userList.GroupBy( u => u.GroupID ).ToList();
122
lancscoder
var groupedCustomerList = userList
    .GroupBy(u => u.GroupID)
    .Select(grp => grp.ToList())
    .ToList();
273
Lee

Votre relevé de groupe sera groupé par ID de groupe. Par exemple, si vous écrivez ensuite:

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

cela devrait bien fonctionner. Chaque groupe a une clé, mais contient également un IGrouping<TKey, TElement> qui est une collection qui vous permet de parcourir plusieurs fois les membres du groupe. Comme le mentionne Lee, vous pouvez convertir chaque groupe en une liste si vous le souhaitez vraiment, mais si vous voulez simplement parcourir ces groupes comme indiqué dans le code ci-dessus, vous n'avez aucun avantage réel à le faire.

34
Jon Skeet

Pour type

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

collection

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

notre requête linq ressemble à celle ci-dessous

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

ou pour tableau au lieu de liste comme ci-dessous

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