2011-09-30 17 views
15

Me gustaría tomar una lista de objetos y convertirla a un diccionario donde la clave es un campo en el objeto, y el valor es una lista de un diferente campo en los objetos que coinciden con la clave. Puedo hacer esto ahora con un bucle, pero creo que esto debería poder lograrse con linq y sin tener que escribir el bucle. Estaba pensando en una combinación de GroupBy y ToDictionary pero hasta ahora no he tenido éxito.Convertir la lista <MyObject> al Diccionario <obj.string, Lista <obj.ID>>

Así es como lo estoy haciendo ahora mismo:

var samplesWithSpecificResult = new Dictionary<string, List<int>>(); 
foreach(var sample in sampleList) 
{ 
    List<int> sampleIDs = null; 
    if (samplesWithSpecificResult.TryGetValue(sample.ResultString, out sampleIDs)) 
    { 
     sampleIDs.Add(sample.ID); 
     continue; 
    } 
    sampleIDs = new List<int>(); 
    sampleIDs.Add(sample.ID); 
    samplesWithSpecificResult.Add(sample.ResultString, sampleIDs); 
} 

Lo más lejos que puedo conseguir con .GroupBy().ToDictionay() es Dictionary<sample.ResultString, List<sample>>.

Cualquier ayuda sería apreciada.

+0

Aprende a amar la [Búsqueda] (http: // MSDN. microsoft.com/en-us/library/bb460184.aspx) –

Respuesta

28

intente lo siguiente

var dictionary = sampleList 
    .GroupBy(x => x.ResultString, x => x.ID) 
    .ToDictionary(x => x.Key, x => x.ToList()); 

El grupo voluntad GroupBy párrafo todos Sample ejemplo, en la lista por su miembro de ResultString, pero mantendrá sólo la parte Id de cada muestra. Esto significa que cada elemento será un IGrouping<string, int>.

La parte ToDictionary utiliza Key del IGrouping<string, int> como la clave del diccionario. IGrouping<string, int> implementa IEnumerable<int> y, por lo tanto, podemos convertir esa colección de muestras 'Id en List<int> con una llamada a ToList, que se convierte en Value del diccionario correspondiente a Key.

+0

Esto es exactamente lo que estaba buscando. ¡Gracias! – Marcus

1
var samplesWithSpecificResult = 
    sampleList.GroupBy(s => s.ResultString) 
       .ToDictionary(g => g.Key, g => g.Select(s => s.ID).ToList()); 

Lo que estamos haciendo aquí es agrupar las muestras en función de su ResultString - esto los pone en un IGrouping<string, Sample>. Luego proyectamos la colección de IGrouping s en un diccionario, usando Key de cada uno como la clave del diccionario y enumerando sobre cada agrupación (IGrouping<string, Sample> también es IEnumerable<Sample>) para seleccionar ID de cada muestra para hacer una lista del valor del diccionario.

2

Sí, super simple. La clave es que cuando haces un GroupBy en IEnumerable<T>, cada "grupo" es un objeto que implementa IEnumerable<T> también (por eso puedo decir g.Select debajo, y estoy proyectando los elementos de la secuencia original con una clave común):

var dictionary = 
    sampleList.GroupBy(x => x.ResultString) 
       .ToDictionary(
        g => g.Key, 
        g => g.Select(x => x.ID).ToList() 
    ); 

Sede, el resultado de sampleList.GroupBy(x => x.ResultString) es un IEnumerable<IGrouping<string, Sample>> y IGrouping<T, U> implementos IEnumerable<U> para que cada grupo es una secuencia de Sample con la clave común!

3
Dictionary<string, List<int>> resultDictionary = 
(
    from sample in sampleList 
    group sample.ID by sample.ResultString 
).ToDictionary(g => g.Key, g => g.ToList()); 

Es posible que desee considerar el uso de una búsqueda en lugar del Diccionario de las listas

ILookup<string, int> idLookup = sampleList.ToLookup(
    sample => sample.ResultString, 
    sample => sample.ID 
); 

utiliza thusly

foreach(IGrouping<string, int> group in idLookup) 
{ 
    string resultString = group.Key; 
    List<int> ids = group.ToList(); 
    //do something with them. 
} 

//and 

List<int> ids = idLookup[resultString].ToList(); 
+0

La búsqueda es una buena idea y algo con lo que definitivamente jugaré. ¡Gracias! – Marcus

Cuestiones relacionadas