反转多对多字典<键,列表<值=“”>&gt; </键,>

时间:2009-08-24 23:38:32

标签: c# dictionary

实际上my previous question让我思考 我意识到逆转Dictionary并非易事。 什么是最优雅和可读的方式?

相同的情景学生多对多的班级

原始Dicitonary<int, List<int>>,其中密钥为studentId,而值为List<int>,其中包含classId并希望恢复为Dictionary<classId, List<studentId>>

由于

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

3 个答案:

答案 0 :(得分:46)

要反转字典很容易:

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

就是这样。

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

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

对于第一部分,我们将使用SelectMany的重载

  

“将序列的每个元素投影到   一个IEnumerable&lt; T&gt;,   将得到的序列展平成   一个序列,并调用一个结果   每个元素的选择器功能   在其中“

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

答案 1 :(得分:8)

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

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 :(得分:3)

我不确定这与your previous question的确切区别。

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

窃取和修改Mehrdad's answer to your other question

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