Sử dụng Linq để nhóm một danh sách các đối tượng thành một danh sách các đối tượng được nhóm mới


149

Tôi không biết nếu điều này có thể xảy ra ở Linq nhưng ở đây sẽ ...

Tôi có một đối tượng:

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

Tôi trả về một danh sách có thể trông như sau:

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

Tôi muốn có thể chạy truy vấn Linq trong danh sách trên, nhóm tất cả người dùng theo GroupID. Vì vậy, đầu ra sẽ là một danh sách các danh sách người dùng có chứa người dùng (nếu điều đó có ý nghĩa?). Cái gì đó như:

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

Tôi đã thử sử dụng mệnh đề linq nhóm nhưng điều này dường như trả về một danh sách các khóa và nó không được nhóm một cách chính xác:

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

Câu trả lời:


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

1
rất đẹp, chỉ là những gì tôi cần. cảm ơn bạn. làm điều này theo cách bắt buộc hút.
dùng1841243

1
Nó có hoạt động tốt không? bởi vì tôi đã sử dụng những cách này không hiệu quả. objModel.tblDonars.groupBy (t => new {t.CreatedOn.Year, t.CreatedOn.Month, t.CreatedOn.Day}). Chọn (g => new {tblDonar = g.ToList ()}). ); việc này không hiệu quả ... bạn có thể giúp ....
Rajamohan Anguchamy

với giải pháp của bạn, nó hoạt động tốt nhưng tôi có một câu hỏi, giả sử trong nhóm có tới 8 giá trị và tôi muốn chỉ cần trong mỗi nhóm chỉ với 6 lần, vậy làm thế nào để làm điều đó xin vui lòng cho tôi biết.
coderwill

Có cách nào để liệt kê riêng UserNames và UserIDs sau khi nhóm theo GroupID không? như - {"1", [1, 2, 4], ["UserOne", "UserTwo", "UserFour"]} cho nhómID 1.
Ajay Aradhya

1
Hiện tại mã không hoạt động và gây ra lỗi nếu bạn cố chuyển nó sang loại danh sách trước đó. Bởi vì việc trả về Danh sách được chọn sẽ tạo Danh sách bên trong danh sách không phải là đầu ra mong muốn ở đây. Đối với những người có vấn đề, tôi có thể đề xuất: var groupedCustomerList = userList.groupBy (u => u.groupID) .Select (grp => grp.First ()). ToList ();
aliassce

36

Tuyên bố nhóm của bạn sẽ nhóm theo ID nhóm. Ví dụ: nếu bạn viết:

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

Điều đó sẽ làm việc tốt. Mỗi nhóm một khóa, nhưng cũng chứa một khóa IGrouping<TKey, TElement>là một bộ sưu tập cho phép bạn lặp lại các thành viên của nhóm. Như Lee đề cập, bạn có thể chuyển đổi từng nhóm thành một danh sách nếu bạn thực sự muốn, nhưng nếu bạn chỉ lặp đi lặp lại chúng theo mã ở trên, sẽ không có lợi ích thực sự khi làm như vậy.


4

Đối với loại

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

bộ sưu tập

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

truy vấn linq của chúng tôi trông như dưới đây

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

hoặc cho mảng thay vì danh sách như dưới đây

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

Vẫn là một câu hỏi cũ, nhưng câu trả lời từ Lee đã không cho tôi nhóm. Kết quả là. Do đó, tôi đang sử dụng câu lệnh sau để nhóm danh sách và trả về danh sách được nhóm:

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

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

Mỗi nhóm hiện có một khóa, nhưng cũng chứa một IGrouping, đây là một bộ sưu tập cho phép bạn lặp lại các thành viên của nhóm.


Điều này trả lời câu hỏi của bạn , không phải câu hỏi của OP. Họ chỉ muốn một danh sách các danh sách. Mã của bạn không cung cấp điều đó.
Gert Arnold

Tôi đã đăng giải pháp này vì câu trả lời được chấp nhận ở trên từ @Lee không hoạt động khi lặp vì nó không cung cấp group.keyphần tử khi lặp qua danh sách được nhóm như trong câu trả lời của @JohnSkeet. Câu trả lời được cung cấp của tôi không cung cấp phần tử group.key khi lặp. Vì vậy, nó có thể giúp người khác rơi vào cái bẫy mà các câu trả lời được cung cấp không hoạt động như được hiển thị ở trên. Vì vậy, nó chỉ là một cách khác để có được danh sách với lợi ích của việc lấy phần tử group.key tương tự như câu trả lời được chấp nhận. Không hiểu yêu cầu của bạn @GertArnold. (.net core 3.0)
datapool

Tôi nghĩ rằng toàn bộ câu hỏi dựa trên sự thiếu hiểu biết IGroupinglà gì . Đó là lý do tại sao OP loại bỏ mã chính xác của họ ở phía dưới, về cơ bảngiống với mã của bạn. Đó là lý do tại sao họ chấp nhận một câu trả lời cung cấp chính xác những gì họ yêu cầu. Những gì họ cần là một lời giải thích, mà JS cung cấp đầy đủ.
Gert Arnold
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.