Использование Linq для группировки списка объектов в новый сгруппированный список списка объектов

Я не знаю, возможно ли это в Linq, но здесь идет...

У меня есть объект:

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

Я возвращаю список, который может выглядеть следующим образом:

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

Я хочу иметь возможность запускать запрос Linq в приведенном выше списке, который группирует всех пользователей по GroupID. Таким образом, вывод будет списком списков пользователей, который содержит пользователя (если это имеет смысл?). Что-то вроде:

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, но похоже, что он возвращает список ключей и его не сгруппированы правильно:

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

Любая помощь будет высоко оценена.

Спасибо

Ответ 1

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

Ответ 2

Ваш групповой оператор будет группироваться по идентификатору группы. Например, если вы пишете:

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

который должен работать нормально. Каждая группа имеет ключ, но также содержит IGrouping<TKey, TElement>, который представляет собой коллекцию, которая позволяет вам перебирать членов группы. Как упоминает Ли, вы можете конвертировать каждую группу в список, если хотите, но если вы просто собираетесь перебирать их в соответствии с приведенным выше кодом, нет никакой реальной выгоды при этом.

Ответ 3

Для типа

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

коллекция

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 выглядит ниже

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

или для массива вместо списка, как показано ниже

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