[c#] Using Linq to group a list of objects into a new grouped list of list of objects

I don't know if this is possible in Linq but here goes...

I have an object:

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

I return a list that may look like the following:

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

I want to be able to run a Linq query on the above list that groups all the users by GroupID. So the output will be a list of user lists that contains user (if that makes sense?). Something like:

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

I've tried using the groupby linq clause but this seems to return a list of keys and its not grouped by correctly:

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

This question is related to c# linq

The answer is


Still an old one, but answer from Lee did not give me the group.Key as result. Therefore, I am using the following statement to group a list and return a grouped list:

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

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

Each group now has a key, but also contains an IGrouping which is a collection that allows you to iterate over the members of the group.


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

our linq query look like below

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

or for array instead of list like below

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

Your group statement will group by group ID. For example, if you then write:

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

that should work fine. Each group has a key, but also contains an IGrouping<TKey, TElement> which is a collection that allows you to iterate over the members of the group. As Lee mentions, you can convert each group to a list if you really want to, but if you're just going to iterate over them as per the code above, there's no real benefit in doing so.