การใช้ Linq เพื่อจัดกลุ่มรายการวัตถุลงในรายการจัดกลุ่มใหม่ของรายการวัตถุ


149

ฉันไม่รู้ว่านี่เป็นไปได้ใน 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 clause แต่ดูเหมือนว่าจะส่งคืนรายการของคีย์และไม่ได้จัดกลุ่มตามอย่างถูกต้อง:

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

คำตอบ:


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

1
ดีมากสิ่งที่ฉันต้องการ ขอบคุณ. การทำเช่นนี้เป็นวิธีที่จำเป็นครับ
user1841243

1
มันทำงานได้ดีไหม เพราะฉันใช้วิธีนี้ไม่ได้ผล objModel.tblDonars.GroupBy (t => ใหม่ {t.CreatedOn.Year, t.CreatedOn.Month, t.CreatedOn.Day}) เลือก (g => ใหม่ {tblDonar = g.ToList ()} ); มันไม่ทำงาน ... คุณสามารถช่วย ....
Rajamohan Anguchamy

ด้วยวิธีการแก้ปัญหาของคุณมันทำงานได้ดี แต่ฉันมีหนึ่งคำถามที่คิดว่าในกลุ่มถึง 8 ค่าและฉันต้องการเพียงแค่ในทุกกลุ่มที่มีเพียง 6 ใช้เวลาดังนั้นวิธีการที่สามารถทำโปรดแจ้งให้เราทราบ
coderwill

มีวิธีการในการแสดงรายชื่อผู้ใช้และหมายเลขผู้ใช้แยกต่างหากหลังจากจัดกลุ่มโดย GroupID หรือไม่ เช่น - {"1", [1, 2, 4], ["UserOne", "UserTwo", "UserFour"]} สำหรับกลุ่ม ID 1
Ajay Aradhya

1
ปัจจุบันรหัสไม่ทำงานและทำให้เกิดข้อผิดพลาดหากคุณลองส่งไปยังรายการประเภทก่อนหน้า เพราะกลับรายการในเลือกสร้างรายการภายในรายการที่ไม่ได้เป็นผลลัพธ์ที่ต้องการที่นี่ สำหรับผู้ที่มีปัญหาฉันสามารถแนะนำ: var GROUPCustomerList = userList.GroupBy (u => u.GroupID) .Select (grp => grp.First ()) ToList ();
aliassce

36

คำสั่งกลุ่มของคุณจะจัดกลุ่มตามรหัสกลุ่ม ตัวอย่างเช่นถ้าคุณเขียนแล้ว:

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

ที่ควรจะทำงานได้ดี แต่ละกลุ่มมีกุญแจ แต่ยังมีกลุ่มIGrouping<TKey, TElement>ซึ่งเป็นชุดที่ช่วยให้คุณสามารถย้ำกว่าสมาชิกของกลุ่ม ในฐานะที่ลีกล่าวถึงคุณสามารถแปลงแต่ละกลุ่มเป็นรายการถ้าคุณต้องการจริงๆ แต่ถ้าคุณเพียงแค่ทำซ้ำพวกเขาตามรหัสข้างต้นไม่มีประโยชน์จริงในการทำเช่นนั้น


4

สำหรับประเภท

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

-1

ยังเป็นของเก่า แต่คำตอบจากลีไม่ได้ให้กลุ่มฉันเลย ดังนั้นฉันใช้คำสั่งต่อไปนี้เพื่อจัดกลุ่มรายการและส่งคืนรายการที่จัดกลุ่ม:

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

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

แต่ละกลุ่มตอนนี้มีคีย์ แต่ยังมีการจัดกลุ่ม IGrouping ซึ่งเป็นคอลเลกชันที่ช่วยให้คุณสามารถย้ำผ่านสมาชิกของกลุ่ม


คำถามนี้ตอบคำถามของคุณไม่ใช่คำถามของ OP พวกเขาต้องการรายการเท่านั้น รหัสของคุณไม่ได้ระบุไว้
Gert Arnold

ฉันโพสต์โซลูชันนี้แล้วเนื่องจากคำตอบที่ได้รับการยอมรับด้านบนจาก @Lee ไม่สามารถใช้งานได้เมื่อวนซ้ำเนื่องจากไม่ได้จัดเตรียมgroup.keyองค์ประกอบเมื่อทำการวนซ้ำผ่านรายการที่จัดกลุ่มอย่างเช่น @JohnSkeet ที่แสดงในคำตอบ คำตอบที่ฉันให้จะมีองค์ประกอบ group.key เมื่อทำซ้ำ ดังนั้นอาจช่วยคนอื่นตกหลุมพรางว่าคำตอบที่ให้ไว้ไม่ทำงานตามที่แสดงด้านบน ดังนั้นจึงเป็นอีกวิธีหนึ่งในการรับรายการพร้อมประโยชน์ในการรับองค์ประกอบ group.key คล้ายกับคำตอบที่ยอมรับ อย่าเข้าใจการอ้างสิทธิ์ของคุณ @GertArnold (หลัก .net 3.0)
Datapool

ฉันคิดว่าคำถามทั้งหมดขึ้นอยู่กับการขาดความเข้าใจในสิ่งที่IGroupingเป็น นั่นเป็นสาเหตุที่ OP ทิ้งรหัสที่ถูกต้องของตัวเองที่ด้านล่างซึ่งก็เหมือนกับรหัสของคุณ นั่นเป็นเหตุผลที่พวกเขายอมรับคำตอบที่ให้สิ่งที่พวกเขาขอ สิ่งที่พวกเขาต้องการคือคำอธิบายซึ่ง JS จัดให้อย่างเพียงพอ
Gert Arnold
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.