Обратный словарь «многие ко многим» <ключ, список <value>> - PullRequest
23 голосов
/ 25 августа 2009

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

Ученик по сценарию «многие ко многим» с классами

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

Спасибо

Обновление: На самом деле, я только что проверил решения Люка и Бруно, и они вернут правильное количество классифицированных, кто бы у них ни был один и тот же ученик, будет обновляться по мере продвижения.

Ответы [ 3 ]

46 голосов
/ 25 августа 2009

Перевернуть словарь очень просто:

var newDic = oldDic.ToDictionary(x => x.Value, x => x.Key);

Вот и все.

Теперь ваш вопрос другой. Речь идет об изменении отношения «многие ко многим», установленного в словаре.

Итак, допустим, у вас есть словарь >. Идея состоит в том, чтобы извлечь из этого «средний стол» отношения «многие ко многим». Затем вы можете перегруппировать его на другой стороне и преобразовать в словарь.

Для первой части мы будем использовать перегрузку SelectMany, которая

"Проецирует каждый элемент последовательности на IEnumerable , выравнивает полученные последовательности в одна последовательность, и вызывает результат функция выбора на каждом элементе в нем. "

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);
8 голосов
/ 25 августа 2009

Немного по-другому (в любом случае, немного более понятным для моего мозга :) ...

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() );
}
3 голосов
/ 25 августа 2009

Я не совсем уверен, чем это отличается от вашего предыдущего вопроса .

Если вы просто спрашиваете, как вернуть 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());
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...