Група LINQ в об’єкт словника


161

Я намагаюся використовувати LINQ для створення Dictionary<string, List<CustomObject>>з List<CustomObject>. Я можу змусити це працювати за допомогою "var", але я не хочу використовувати анонімні типи. Ось що я маю

var x = (from CustomObject o in ListOfCustomObjects
      group o by o.PropertyName into t
      select t.ToList());

Я також намагався використовувати Cast<>()з бібліотеки LINQ один раз x, але я отримую проблеми з компіляцією, тому що це недійсний склад.


Що робити, якщо ви спробуйте var x = (з CustomObject o у групі ListOfCustomObjects o за допомогою o.PropertyName в t виберіть t) .ToList ();
esastincy

44
Чи є якась причина, чому вам потрібно це зробити, а не використовувати ToLookup, який призначений для цього?
Джон Скіт

1
Джон, чи не могли б ви опублікувати приклад того, як ToLookup працює в цій ситуації? Я не знайомий із тим методом LINQ.
Atari2600

8
@JonSkeet Ти приголомшливий! (Я маю на увазі, всі це вже знали, але все ж.) Причина, по якій я не планував використовувати ToLookup, була тому, що я досі про це не чув. Тепер я знаю!
neminem

1
Для повноти, якщо varне використовується тип "анонімний", він використовується "неявний" тип. Анонімні типи - це нові класи, створені компілятором для обробки конструкції new { thing = "stuff" };. Неявні типи - це існуючі класи, varце просто зручний спосіб посилання на них, коли змінна призначається негайно, про тип змінної можна зробити висновок з типу об'єкта, який їй присвоюється. Можна навіть неявно ввести змінну, що посилається на анонімний тип, тобто:var a = new { thing = "stuff" };
Майкл Блекберн

Відповіді:


351
Dictionary<string, List<CustomObject>> myDictionary = ListOfCustomObjects
    .GroupBy(o => o.PropertyName)
    .ToDictionary(g => g.Key, g => g.ToList());

6
Якщо вам не потрібна властивість з "CustomObject" як значення списку (не вказано в цій відповіді), варто перевірити його кодифікацію коментаря Джона Скіта до питання, що рекомендує ToLookup ().
Шон

3
це спосіб зробити це, якщо бажаний непорушний результат. ToLookup незмінний.
Аміт

1
Мої 2 центи (просто тому, що це змусило мене боротися протягом години :)): при групуванні за властивостями переконайтесь, що властивість має значення! Інакше метод Todict не спрацьовує ключ (для String-Properties принаймні ...) :)
dba

.GroupBy(o => o.PropertyName).ToDictionary(g => g.Key, g => g.ToList())Це може бути частиною розширення бібліотеки Linq. тож нам залишається лише робити.ToDictionary(o=>o.PropertyName)
Джайдер

3
@Jaider, вже є така функціональність: просто замініть ToDictionaryна ToLookup.
Роберт Синорадзкі

19

Я не можу коментувати @Michael Blackburn, але, мабуть, ти отримав суттєвий результат, оскільки GroupBy в цьому випадку не потрібен.

Використовуйте його так:

var lookupOfCustomObjects = listOfCustomObjects.ToLookup(o=>o.PropertyName);
var listWithAllCustomObjectsWithPropertyName = lookupOfCustomObjects[propertyName]

Крім того, я бачив це ефективніше, ніж при використанні GroupBy (). ToDictionary ().


Я виконував транслітерацію, не відповідаючи на запитання найкращим чином.
Майкл Блекберн

1

Для @ atari2600 ось так виглядає відповідь, використовуючи ToLookup у лямбда-синтаксисі:

var x = listOfCustomObjects
    .GroupBy(o => o.PropertyName)
    .ToLookup(customObject => customObject);

В основному, він приймає IGrouping і матеріалізує його для вас у словник списків зі значеннями PropertyName як ключовими.


Чому потік? Це не точно / відповідає на запитання?
Майкл Блекберн

1
У випадку, якщо ви пропустили його, @RuudvK у своїй відповіді згадав, що підозрює, що він має право на те, що груповий зв'язок є непотрібним. ToLookupмає перевантаження, яка дозволить виконати роботу.
Джефф Б

Я пропустив цю відповідь, дякую, що позначили мене. Має сенс, що Групування є синтаксично непотрібним, я лише залишаю це, щоб зробити перехід від синтаксису запитів до синтаксису методу більш чітким.
Майкл Блекберн

GroupBy (перевантаження лише одним параметром) повертає IEnumerable <IGrouping <TKey, TSource >> подальший ToLookup потім перетворює його у досить складний тип, який навіть не схожий на IDictionary <TKey, IList <TSource>> просто ToLookup повертає належний тип.
xtofs

-1

Наступне працювало для мене.

var temp = ctx.Set<DbTable>()
  .GroupBy(g => new { g.id })
  .ToDictionary(d => d.Key.id);
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.