213 votes

Utilisation de Linq pour grouper une liste d'objets en une nouvelle liste groupée de listes d'objets

Je ne sais pas si c'est possible en Linq, mais voici...

J'ai un objet :

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

Je renvoie une liste qui peut ressembler à ce qui suit :

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 souhaite pouvoir exécuter une requête Linq sur la liste ci-dessus qui regroupe tous les utilisateurs par GroupID. La sortie sera donc une liste de listes d'utilisateurs contenant user (si cela a un 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 linq groupby mais cela semble renvoyer une liste de clés et ce n'est pas groupé correctement :

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

427voto

Lee Points 63849
var groupedCustomerList = userList
    .GroupBy(u => u.GroupID)
    .Select(grp => grp.ToList())
    .ToList();

43voto

Jon Skeet Points 692016

Votre déclaration de groupe se groupe 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 fonctionner correctement. Chaque groupe a une clé, mais contient également un IGrouping<TKey, TElement> qui est une collection permettant d'itérer sur les membres du groupe. Comme le mentionne Lee, vous pouvez convertir chaque groupe en liste si vous le souhaitez vraiment, mais si vous ne faites qu'itérer sur eux comme dans le code ci-dessus, il n'y a pas de réel avantage à le faire.

5voto

sangram Points 46

Pour le 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 à ce qui suit

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

ou pour un tableau au lieu d'une 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>() };

0voto

datapool Points 143

Il s'agit toujours d'une vieille question, mais la réponse de Lee ne m'a pas donné la clé de groupe comme résultat. Par conséquent, j'utilise l'instruction suivante pour grouper une liste et renvoyer une liste groupée :

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

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

Chaque groupe possède désormais une clé, mais contient également un IGrouping, qui est une collection permettant d'itérer sur les membres du groupe.

-3voto

Rodlaiz Points 5

Aujourd'hui, vous pouvez utiliser la fonction FindAll() de Linq.

var groupedCustomerList = userList.FindAll( u => u.GroupID);

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X