LINQ Group By в объект словаря

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, но у меня возникают проблемы с компиляцией, из-за того, что это неверное приведение.

Atari 2600
источник
Что если вы попробуете var x = (из CustomObject o в группе ListOfCustomObjects o с помощью o.PropertyName в t select t) .ToList ();
esastincy
44
Есть ли какая-то причина, почему вам нужно сделать это, а не использовать ToLookup, который предназначен для этого?
Джон Скит
1
Джон, не могли бы вы опубликовать пример того, как ToLookup работает в этой ситуации? Я не знаком с этим методом LINQ.
Atari2600
8
@JonSkeet Ты классный! (Я имею в виду, что все это уже знали, но все же.) Причина, по которой я не планировал использовать ToLookup, заключалась в том, что я никогда не слышал об этом до сих пор. Теперь я знаю!
Неминем,
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)
Jaider
3
@Jaider, там уже есть такая функциональность: просто заменить ToDictionaryна ToLookup.
Роберт Синорадски
19

Я не могу комментировать @Michael Blackburn, но, думаю, вы поняли, потому что GroupBy в этом случае не нужен.

Используйте это как:

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

Кроме того, я видел, как это работает лучше, чем при использовании GroupBy (). ToDictionary ().

RuudvK
источник
Я выполнял транслитерацию, не отвечая на вопрос наилучшим образом.
Майкл Блэкберн
1

Для @ atari2600 вот как будет выглядеть ответ при использовании ToLookup в лямбда-синтаксисе:

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

По сути, он берет IGrouping и материализует его для вас в словарь списков со значениями PropertyName в качестве ключа.

Майкл Блэкберн
источник
Почему отрицательный голос? Разве это не точно / ответ на вопрос?
Майкл Блэкберн
1
В случае, если вы пропустили это, @RuudvK упомянул в своем ответе, что он подозревает, что понижение рейтинга вызвано тем, что GroupBy не нужен. 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);
Лео Барбас
источник