Подтвердить что ты не робот

Обратный словарь "многие-ко-многим" <ключ, список <значение >>

На самом деле мой предыдущий вопрос заставлял меня думать и я понял, что обращение a Dictionary не является тривиальным. Каков самый элегантный и читаемый способ сделать это?

Студент с одинаковым сценарием Многие для многих с классами

original Dicitonary<int, List<int>>, где ключ studentId, а значение - List<int>, которое содержит classId и хочет вернуться к Dictionary<classId, List<studentId>>

Спасибо

Обновление: На самом деле я только что протестировал решения Luke и Bruno, и они возвращают правильное количество классифицированных, кто бы они ни были у одного и того же студента, будет обновляться, когда я пойду.

4b9b3361

Ответ 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());