Reverse many-to-many Dictionary>

前端 未结 3 1882
再見小時候
再見小時候 2021-02-05 05:41

Actually my previous question got me thinking and I realized that reversing a Dictionary is not trivial. What is the most elegant and readable way to do it?

相关标签:
3条回答
  • 2021-02-05 05:50

    Slightly different way (a bit more comprehensible to my brain anyway :) ...

    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() );
    }
    
    0 讨论(0)
  • 2021-02-05 05:50

    I'm not sure exactly how this differs from your previous question.

    If you're just asking how to return a Dictionary<int, List<int>> rather than Dictionary<int, IEnumerable<int>> then all you need is a call to the ToList method.

    Stealing and amending 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());
    
    0 讨论(0)
  • To reverse a dictionary is very easy:

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

    That's all.

    Now, your question is different. It is about reversing a many-to-many relationship, established on a dictionary.

    So, let's say you have Dictionary<TEntity1, IEnumerable<TEntity2>>. The idea is to extract from this the "middle table" of the many-to-many relationship. Then you can regroup it by the other side, and retransform into a dictionary.

    For the first part, we will use the overload of SelectMany that

    "Projects each element of a sequence to an IEnumerable<T>, flattens the resulting sequences into one sequence, and invokes a result selector function on each element therein."

    var table =
        dict.SelectMany(
            x => x.Value,
            (dictEntry, entryElement) => new
                   {
                          Entity1 = dictEntry.Key,
                          Entity2 = entryElement
                   }
        );
    

    So, now you just have to regroup this table the way you want, and then convert it to a dictionary.

     var newDict =
         table
             .GroupBy(x => x.Entity2,
                      x => x.Entity1,
                      (entity2, entity1) => new {entity1, entity2})
             .ToDictionary(x => x.entity2, x => x.entity1);
    
    0 讨论(0)
提交回复
热议问题