Обратный словарь "многие-ко-многим" <ключ, список <значение >>
На самом деле мой предыдущий вопрос заставлял меня думать
и я понял, что обращение a Dictionary
не является тривиальным.
Каков самый элегантный и читаемый способ сделать это?
Студент с одинаковым сценарием Многие для многих с классами
original Dicitonary<int, List<int>>
, где ключ studentId, а значение - List<int>
, которое содержит classId и хочет вернуться к Dictionary<classId, List<studentId>>
Спасибо
Обновление:
На самом деле я только что протестировал решения Luke и Bruno, и они возвращают правильное количество классифицированных, кто бы они ни были у одного и того же студента, будет обновляться, когда я пойду.
Ответы
Ответ 1
Немного другой способ (немного более понятный для моего мозга:):)
var newDict = new Dictionary<int, List<int>>();
var dict = new Dictionary<int, List<int>>();
dict.Add( 1, new List<int>() { 1, 2, 3, 4, 5 } );
dict.Add( 2, new List<int>() { 1, 2, 3, 4, 5 } );
dict.Add( 3, new List<int>() { 1, 2, 6 } );
dict.Add( 4, new List<int>() { 1, 6, 7 } );
dict.Add( 5, new List<int>() { 8 } );
var newKeys = dict.Values.SelectMany( v => v ).Distinct();
foreach( var nk in newKeys )
{
var vals = dict.Keys.Where( k => dict[k].Contains(nk) );
newDict.Add( nk, vals.ToList() );
}
Ответ 2
Отменить словарь очень просто:
var newDic = oldDic.ToDictionary(x => x.Value, x => x.Key);
Что все.
Теперь ваш вопрос другой. Речь идет об изменении отношения "многие ко многим", установленного в словаре.
Итак, скажем, у вас есть словарь < TEntity1, IEnumerable < TEntity2 → . Идея состоит в том, чтобы извлечь из этого "среднюю таблицу" отношений "многие ко многим". Затем вы можете перегруппировать его с другой стороны и повторно преобразовать в словарь.
В первой части мы будем использовать перегрузку SelectMany, которая
"Проецирует каждый элемент последовательности в IEnumerable <T> , выравнивает полученные последовательности в одной последовательности и вызывает результат селекторная функция для каждого элемента в ней".
var table =
dict.SelectMany(
x => x.Value,
(dictEntry, entryElement) => new
{
Entity1 = dictEntry.Key,
Entity2 = entryElement
}
);
Итак, теперь вам просто нужно перегруппировать эту таблицу так, как вы хотите, а затем преобразовать ее в словарь.
var newDict =
table
.GroupBy(x => x.Entity2,
x => x.Entity1,
(entity2, entity1) => new {entity1, entity2})
.ToDictionary(x => x.entity2, x => x.entity1);
Ответ 3
Я не уверен, как это отличается от вашего предыдущего вопроса.
Если вы просто спрашиваете, как вернуть Dictionary<int, List<int>>
, а не Dictionary<int, IEnumerable<int>>
, тогда вам понадобится только вызов ToList
.
Кража и изменение Мехрдад ответит на ваш другой вопрос:
var classToStudent = studentToClass
.SelectMany(
pair => pair.Value.Select(val => new { Key = val, Value = pair.Key }))
.GroupBy(item => item.Key)
.ToDictionary(gr => gr.Key, gr => gr.Select(item => item.Value).ToList());