LINQ - GroupBy ключ, а затем поместить каждый сгруппированный элемент в отдельные «корзины» - PullRequest
14 голосов
/ 08 июля 2011

У меня есть список таких предметов:

public class Item
{
    public int ItemId { get; set; }
    public string ItemName { get; set; }
    public int ListId { get; set; }
}

1 Test1 1

2 Test2 1

3 Test3 1

4 List 2

5 List2 2

6 Testing 3

7 Testing2 3

8 Testing3 3

Есть ли способ для менясгруппируйте по ListId и поместите их в каждое отдельное ведро, т. е. у ведра ListId1 будут все элементы с ListId == 1.Список динамически возвращается из SQL, поэтому я не знаю заранее, сколько будет ListId.

Ответы [ 3 ]

20 голосов
/ 08 июля 2011

Вы можете использовать GroupBy :

var groups = items.GroupBy(item => item.ListId);

foreach(var group in groups)
{
     Console.WriteLine("List with ID == {0}", group.Key);
     foreach(var item in group)
        Console.WriteLine("    Item: {0}", item.ItemName);
}
10 голосов
/ 15 мая 2015

Давайте создадим ваш список предметов:

List<Item> items = new List<Item>();
items.Add(new Item() { ItemId = 1, ItemName = "Test1", ListId = 1 });
items.Add(new Item() { ItemId = 2, ItemName = "Test2", ListId = 1 });
items.Add(new Item() { ItemId = 3, ItemName = "Test3", ListId = 1 });
items.Add(new Item() { ItemId = 4, ItemName = "List", ListId = 2 });
items.Add(new Item() { ItemId = 5, ItemName = "List2", ListId = 2 });
items.Add(new Item() { ItemId = 6, ItemName = "Testing", ListId = 3 });
items.Add(new Item() { ItemId = 7, ItemName = "Testing2", ListId = 3 });
items.Add(new Item() { ItemId = 8, ItemName = "Testing3", ListId = 3 });

var groupByResult = items.GroupBy(i => i.ListId);

После этого вызова GroupBy groupByResult - это переменная типа IEnumerable<IGrouping<int, Item>>, которая в основном представляет собой набор объектов, реализующих интерфейс IGrouping. Это позволяет вам перебирать все элементы, поскольку IGrouping является производным от IEnumerable<> и имеет дополнительное поле с именем Key:

public interface IGrouping<out TKey, out TElement> : IEnumerable<TElement>, IEnumerable
{
    TKey Key { get; }
}

Вкратце, вызов метода GroupBy возвращает список списков . Внешний список соответствует «корзинам», как вы упомянули в своем вопросе. Затем каждое «ведро» содержит элементы, соответствующие этому «ведру». Чтобы быть конкретным для вашего примера, значение groupByResult изображено на этом снимке экрана. Как мы видим, ваша первоначальная коллекция была сгруппирована в три разных сегмента, которые содержат 3, 2 и 3 элемента соответственно.

Что касается доступа к элементам в этих группах, вы можете использовать простой LINQ:

List<Item> firstBucketItems = groupByResult.First(i => i.Key == 1).ToList();
List<Item> secondBucketItems = groupByResult.First(i => i.Key == 2).ToList();
List<Item> thirdBucketItems = groupByResult.First(i => i.Key == 3).ToList();

First bucket items

Или вы можете просто перебрать все элементы:

foreach (var itemGroup in groupByResult)
{
    int groupKey = itemGroup.Key;

    foreach (Item item in itemGroup)
    {
        // Do whatever...
    }
}
0 голосов
/ 22 мая 2018
    IList<Student> studentList = new List<Student>()
    { 
    new Student() { StudentID = 1, StudentName = "John", Age = 18 } ,
    new Student() { StudentID = 2, StudentName = "Steve",  Age = 21 } ,
    new Student() { StudentID = 3, StudentName = "Bill",  Age = 18 } ,
    new Student() { StudentID = 4, StudentName = "Ram" , Age = 20 } ,
    new Student() { StudentID = 5, StudentName = "Abram" , Age = 21 } 
    };

var groupedResult = from s in studentList group s by s.Age;

// повторяем каждую группу

foreach (var ageGroup in groupedResult)
{
    Console.WriteLine("Age Group: {0}", ageGroup.Key); //Each group has a key 

    foreach(Student s in ageGroup) // Each group has inner collection
        Console.WriteLine("Student Name: {0}", s.StudentName);
}
...