c# - elementat - Reverse many-to-many Dictionary<key, List<value>>
c# dictionary vs hashtable (3)
No estoy seguro exactamente en qué se diferencia esto de tu pregunta anterior .
Si solo pregunta cómo devolver un Dictionary<int, List<int>>
lugar de Dictionary<int, IEnumerable<int>>
, todo lo que necesita es una llamada al método ToList
.
Robando y enmendando la respuesta de Mehrdad a tu otra pregunta :
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());
En realidad, mi pregunta anterior me hizo pensar y me di cuenta de que revertir un Dictionary
no es trivial. ¿Cuál es la forma más elegante y legible de hacerlo?
Mismo escenario estudiante Muchos a muchos con clases
original Dicitonary<int, List<int>>
donde la clave es studentId y el Valor es una List<int>
que contiene classId y desea volver al Dictionary<classId, List<studentId>>
Gracias
Actualización: en realidad, acabo de probar las soluciones de Luke y Bruno y me devuelven la cantidad correcta de personas clasificadas, ya que todas tienen el mismo estudiante, se actualizarán a medida que avanzo.
Para revertir un diccionario es muy fácil:
var newDic = oldDic.ToDictionary(x => x.Value, x => x.Key);
Eso es todo.
Ahora, tu pregunta es diferente. Se trata de revertir una relación de muchos a muchos, establecida en un diccionario.
Entonces, digamos que tiene el diccionario <TEntity1, IEnumerable <TEntity2>>. La idea es extraer de esto la "tabla intermedia" de la relación de muchos a muchos. Luego puede reagruparlo por el otro lado y volver a transformarse en un diccionario.
Para la primera parte, utilizaremos la sobrecarga de SelectMany que
"Proyecta cada elemento de una secuencia a un IEnumerable <T>, aplana las secuencias resultantes en una secuencia e invoca una función de selección de resultados en cada elemento".
var table =
dict.SelectMany(
x => x.Value,
(dictEntry, entryElement) => new
{
Entity1 = dictEntry.Key,
Entity2 = entryElement
}
);
Entonces, ahora solo tiene que reagrupar esta tabla de la forma que desee y luego convertirla en un diccionario.
var newDict =
table
.GroupBy(x => x.Entity2,
x => x.Entity1,
(entity2, entity1) => new {entity1, entity2})
.ToDictionary(x => x.entity2, x => x.entity1);
Una forma ligeramente diferente (un poco más comprensible para mi cerebro de todos modos :) ...
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() );
}