Створіть словник у списку з групуванням


106

У мене в списку є такий об’єкт:

public class DemoClass
{
    public int GroupKey { get; set; }
    public string DemoString { get; set; }
    public object SomeOtherProperty { get; set; }
}

Тепер я хочу створити з нього такий словник:

Dictionary<int, List<DemoClass>>

Я хочу згрупувати List<DemoClass>об'єкти за властивостями GroupKey, але я не розумію, як це робиться, і допомогти.

Трохи подумавши, я домігся необхідної поведінки за допомогою:

var groupedDemoClasses = from demoClass in mySepcialVariableWhichIsAListOfDemoClass
                            group demoClass by demoClass.GroupKey
                            into groupedDemoClass
                            select groupedDemoClass;
var neededDictionary = groupedDemoClass.ToDictionary(gdc => gdc.Key, gdc => gdc.ToList());

але чи є спосіб зробити це в єдине твердження?

Відповіді:


88
var groupedDemoClasses = (from demoClass in mySepcialVariableWhichIsAListOfDemoClass
                          group demoClass by demoClass.GroupKey
                          into groupedDemoClass
                          select groupedDemoClass).ToDictionary(gdc => gdc.Key, gdc => gdc.ToList());

Цей буде працювати !!!


198

Просто, щоб зробити пропозицію mquander конкретним:

var groupedDemoClasses = mySpecialVariableWhichIsAListOfDemoClass
                             .GroupBy(x => x.GroupKey)
                             .ToDictionary(gdc => gdc.Key, gdc => gdc.ToList());

Ви зробите це коротше, якщо, звичайно, також використовуєте короткі імена змінних :)

Однак, я можу припустити, що пошук може бути більш підходящим? Пошук - це в основному словник від ключа до ключа IEnumerable<T>- якщо вам справді не потрібні значення як список, це робить код ще коротшим (і більш ефективним) при виклику ToLookup :

var groupedDemoClasses = mySpecialVariableWhichIsAListOfDemoClass
                             .ToLookup(x => x.GroupKey);

1
я подумав, що пошук виконує не так добре, порівняно зі вбудованим словником, у довгостроковій середовищі, завдяки цьому формується новий результат для кожного запиту ... будь ласка, виправте мене, якщо я помиляюся!
Андреас Нідермайр

Ні, це створює весь пошук. Як правило, ToXXX не використовує відкладене виконання.
Джон Скіт

1
(Ви можете думати про групування, яке дійсно відкладено.)
Джон Скіт

1
Якби я не була такою злобною, я би проголосувала за вас. Прийшов за Linq, залишився за структурою даних, про яку я ніколи не чув!
Кріс Макколл

2
@sasikt: Модель полягає в тому, що ви можете шукати що завгодно , і ви просто отримуєте порожню колекцію, якщо ключ не існує. Це часто корисніше, ніж підхід TryGetValue, IMO.
Джон Скіт

6

Ви вже зробили це однолінійним. Просто поставте ToDictionaryкінець першого рядка. Якщо ви хочете, щоб він був коротшим, використовуйте синтаксис функціонального складу замість синтаксису запиту.


3

Я тут трохи переходжу з теми, але я дійшов до цієї теми, тому що я шукав спосіб створити словник словника в Linq, і розмова тут привела мене до відповіді ...

Ви можете використовувати linq для створення багаторівневих словників, що корисно для сценаріїв, де у вас є більше 1 ключа або виміру, за яким ви хочете шукати. Трюк полягає в тому, щоб створити групування та потім перетворити його у словник таким чином:

  Dim qry = (From acs In ActualSales _
             Group By acs.ProductID Into Group _
             Select ProductID, Months = Group.ToDictionary(Function(c) c.Period) _
            ).ToDictionary(Function(c) c.ProductID)

Отриманий запит можна використовувати наступним чином:

 If qry.ContainsKey(_ProductID) Then
      With qry(_ProductID)
          If .Months.ContainsKey(_Period) Then
             ...
          End If
      End With
 End If

Сподіваюся, це корисно для всіх, кому потрібен такий вид запиту.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.