2012-05-25 17 views
20

Tengo una consulta LINQLINQ seleccionar al nuevo objeto

var x = (from t in types select t).GroupBy(g =>g.Type) 

que agrupa objetos por su tipo, como resultado Quiero tener nuevo objeto único que contiene todos los objetos agrupados y su recuento. Algo como esto:

type1, 30  
type2, 43  
type3, 72 

para ser más claro: la agrupación de resultados deben estar en un objeto no es un objeto según el tipo de elemento

Respuesta

24

Leer: 101 LINQ Samples en que LINQ - Grouping Operators desde el sitio de Microsoft MSDN

var x = from t in types group t by t.Type 
     into grp  
     select new { type = grp.key, count = grp.Count() }; 

objeto forsingle hacen uso de StringBuilder y lo añaden que va a hacer o convertir esto en forma de diccionario

// fordictionary 
    var x = (from t in types group t by t.Type 
    into grp  
    select new { type = grp.key, count = grp.Count() }) 
    .ToDictionary(t => t.type, t => t.count); 

    //for stringbuilder not sure for this 
    var x = from t in types group t by t.Type 
     into grp  
     select new { type = grp.key, count = grp.Count() }; 
    StringBuilder MyStringBuilder = new StringBuilder(); 

    foreach (var res in x) 
    { 
     //: is separator between to object 
     MyStringBuilder.Append(result.Type +" , "+ result.Count + " : "); 
    } 
    Console.WriteLine(MyStringBuilder.ToString()); 
+0

Gracias, esto es lo suficientemente bueno para mí – Jeff

19

Todos los objetos agrupados , o todos los tipos ? Suena como puede que sólo quieren:

var query = types.GroupBy(t => t.Type) 
       .Select(g => new { Type = g.Key, Count = g.Count() }); 

foreach (var result in query) 
{ 
    Console.WriteLine("{0}, {1}", result.Type, result.Count); 
} 

EDIT: Si desea en un diccionario, sólo puede utilizar:

var query = types.GroupBy(t => t.Type) 
       .ToDictionary(g => g.Key, g => g.Count()); 

No hay necesidad de seleccionar en parejas y continuación construir el diccionario.

+0

Lo siento por una pregunta no clara. Su solución es muy similar a la que necesito, pero quiero tener todos los resultados de agrupamiento en un solo objeto, no un objeto por tipo – Jeff

+1

@Jeff: la respuesta que ha aceptado es efectivamente la misma que la mía ... solo en un diccionario . Los resultados * son * todos en un solo objeto ('consulta'). Aún no está claro qué es lo que quiere lograr que mi solución no lo haga por usted. Si vas a agrupar por tipo, has * got * para tener un objeto por grupo, pero aquí 'query' es la consulta que * le dará * a todos esos grupos. –

+0

Bueno, sé qué tipos buscaré en una lista agrupada, por lo que tenerlo en el diccionario parece ser lo suficientemente fácil como para crear un objeto fuera de la consulta – Jeff

3
var x = from t in types 
     group t by t.Type into grouped 
     select new { type = grouped.Key, 
        count = grouped.Count() }; 
+0

pregunta complementaria: en general, si seleccionas un nuevo {...} ¿inserta algo en el DB cuando actualizas? –

+0

@DanyKhalife no necesita llamar a updateChanges cuando está utilizando instrucciones select. Si usa, no insertará nada, solo ejecutará una declaración de selección en el DB. – daryal

1

Si desea poder realizar una búsqueda en cada tipo para obtener su frecuencia, deberá transformar la enumeración en un diccionario.

var types = new[] {typeof(string), typeof(string), typeof(int)}; 
var x = types 
     .GroupBy(type => type) 
     .ToDictionary(g => g.Key, g => g.Count()); 
foreach (var kvp in x) { 
    Console.WriteLine("Type {0}, Count {1}", kvp.Key, kvp.Value); 
} 
Console.WriteLine("string has a count of {0}", x[typeof(string)]); 
14

Las respuestas aquí me tienen cerca, pero en el año 2016, yo era capaz de escribir la siguiente LINQ:

List<ObjectType> objectList = similarTypeList.Select(o => 
    new ObjectType 
    { 
     PropertyOne = o.PropertyOne, 
     PropertyTwo = o.PropertyTwo, 
     PropertyThree = o.PropertyThree 
    }).ToList(); 
+1

¡esto es genial e instructivo! ¡Gracias! –

0

Esto es un gran artículo para la sintaxis necesaria para crear nuevos objetos de una consulta LINQ .

Pero, si las asignaciones para completar los campos del objeto son algo más que simples asignaciones, por ejemplo, analizar cadenas a enteros, y una de ellas falla, no es posible depurar esto. No puede crear un punto de interrupción en ninguna de las asignaciones individuales.

Y si mueve todas las asignaciones a una subrutina y devuelve un nuevo objeto desde allí e intenta establecer un punto de interrupción en esa rutina, puede establecer un punto de interrupción en esa rutina, pero el punto de interrupción nunca se disparará.

Así que en lugar de:

var query2 = from c in doc.Descendants("SuggestionItem") 
       select new SuggestionItem 
         { Phrase = c.Element("Phrase").Value 
         Blocked = bool.Parse(c.Element("Blocked").Value), 
         SeenCount = int.Parse(c.Element("SeenCount").Value) 
         }; 

O

var query2 = from c in doc.Descendants("SuggestionItem") 
         select new SuggestionItem(c); 

vez que hice esto:

List<SuggestionItem> retList = new List<SuggestionItem>(); 

var query = from c in doc.Descendants("SuggestionItem") select c; 

foreach (XElement item in query) 
{ 
    SuggestionItem anItem = new SuggestionItem(item); 
    retList.Add(anItem); 
} 

Esto me permitió fácilmente depurar y averiguar qué estaba fallando asignación.En este caso, al XElement le faltaba un campo que estaba analizando para establecer en SuggestionItem.

Me encontré con estos problemas con Visual Studio 2017 mientras escribía pruebas de unidad para una nueva rutina de biblioteca.