反转多对多字典<键,列表>

实际上我之前的问题让我思考,我意识到反转Dictionary并非易事。 什么是最优雅和可读的方式呢?

同样的情景学生多对多与class级

原始Dicitonary<int, List> ,其中键是studentId,Value是包含classId的List ,并且想要恢复为Dictionary<classId, List>

谢谢

更新:实际上我只是测试了Luke和Bruno的解决方案,并且他们返回了适当数量的分类,无论他们都拥有同一个学生,我会随着时间的推移进行更新。

略有不同的方式(无论如何我的大脑更容易理解:) …

 var newDict = new Dictionary>(); var dict = new Dictionary>(); dict.Add( 1, new List() { 1, 2, 3, 4, 5 } ); dict.Add( 2, new List() { 1, 2, 3, 4, 5 } ); dict.Add( 3, new List() { 1, 2, 6 } ); dict.Add( 4, new List() { 1, 6, 7 } ); dict.Add( 5, new List() { 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() ); } 

反转字典很容易:

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

就这样。

现在,你的问题是不同的。 它是关于扭转在字典上建立的多对多关系。

所以,假设你有Dictionary >。 我们的想法是从中提取出多对多关系的“中间表”。 然后你可以在另一边重新组合它,然后重新转换成字典。

对于第一部分,我们将使用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); 

我不确定这与你之前的问题究竟有何不同。

如果您只是询问如何返回Dictionary>而不是Dictionary>那么您只需要调用ToList方法。

偷窃和修改Mehrdad对你的另一个问题的回答 :

 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());