Преобразовать список <MyObject> в словарь <obj.string, List <obj.ID>
Я хотел бы взять список объектов и преобразовать их в словарь, где ключ является полем в объекте, а значение представляет собой список другого поля в объектах, которые соответствуют ключу. Я могу сделать это сейчас с помощью цикла, но я считаю, что это должно быть выполнено с помощью linq и не нужно писать цикл. Я думал о комбинации GroupBy
и ToDictionary
, но пока не увенчался успехом.
Вот как я делаю это прямо сейчас:
var samplesWithSpecificResult = new Dictionary<string, List<int>>();
foreach(var sample in sampleList)
{
List<int> sampleIDs = null;
if (samplesWithSpecificResult.TryGetValue(sample.ResultString, out sampleIDs))
{
sampleIDs.Add(sample.ID);
continue;
}
sampleIDs = new List<int>();
sampleIDs.Add(sample.ID);
samplesWithSpecificResult.Add(sample.ResultString, sampleIDs);
}
Самый дальний я могу получить с .GroupBy().ToDictionay()
- Dictionary<sample.ResultString, List<sample>>
.
Любая помощь будет оценена.
Ответы
Ответ 1
Попробуйте выполнить
var dictionary = sampleList
.GroupBy(x => x.ResultString, x => x.ID)
.ToDictionary(x => x.Key, x => x.ToList());
Предложение GroupBy
будет группировать каждый экземпляр Sample
в списке его членом ResultString
, но будет содержать только часть Id
каждого образца. Это означает, что каждый элемент будет IGrouping<string, int>
.
В разделе ToDictionary
используется Key
IGrouping<string, int>
в качестве словарного ключа. IGrouping<string, int>
реализует IEnumerable<int>
, и поэтому мы можем преобразовать эту коллекцию образцов Id
в List<int>
с вызовом ToList
, который становится Value
словаря для данного Key
.
Ответ 2
Dictionary<string, List<int>> resultDictionary =
(
from sample in sampleList
group sample.ID by sample.ResultString
).ToDictionary(g => g.Key, g => g.ToList());
Возможно, вы захотите использовать Lookup вместо Dictionary of Lists
ILookup<string, int> idLookup = sampleList.ToLookup(
sample => sample.ResultString,
sample => sample.ID
);
используется таким образом
foreach(IGrouping<string, int> group in idLookup)
{
string resultString = group.Key;
List<int> ids = group.ToList();
//do something with them.
}
//and
List<int> ids = idLookup[resultString].ToList();
Ответ 3
Да, супер просто. Ключ в том, что когда вы выполняете GroupBy
on IEnumerable<T>
, каждая "группа" - это объект, который также реализует IEnumerable<T>
(вот почему я могу сказать g.Select
ниже), и я проектирую элементы оригинальная последовательность с общим ключом):
var dictionary =
sampleList.GroupBy(x => x.ResultString)
.ToDictionary(
g => g.Key,
g => g.Select(x => x.ID).ToList()
);
См., результат sampleList.GroupBy(x => x.ResultString)
- это IEnumerable<IGrouping<string, Sample>>
и IGrouping<T, U>
реализует IEnumerable<U>
, так что каждая группа является последовательностью Sample
с общим ключом!
Ответ 4
var samplesWithSpecificResult =
sampleList.GroupBy(s => s.ResultString)
.ToDictionary(g => g.Key, g => g.Select(s => s.ID).ToList());
Что мы делаем здесь, это группировать образцы на основе их ResultString
- это помещает их в IGrouping<string, Sample>
. Затем мы проецируем коллекцию IGrouping
в словарь, используя Key
каждого в качестве словарного ключа и перечисляя по каждой группе (IGrouping<string, Sample>
также IEnumerable<Sample>
), чтобы выбрать ID
каждого образца, чтобы введите список значений словаря.