2012-05-25 21 views
20

Ho una query LINQLinq selezionare al nuovo oggetto

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

che raggruppa gli oggetti dal loro tipo, come risultato voglio avere solo nuovo oggetto che contiene tutti gli oggetti raggruppati e loro conteggio. Qualcosa di simile a questo:

type1, 30  
type2, 43  
type3, 72 

Per essere più chiari: il raggruppamento risultati dovrebbero essere in un oggetto non un oggetto per oggetto tipo

risposta

24

Leggi: 101 LINQ Samples in quel LINQ - Grouping Operators da Microsoft sito MSDN

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

oggetto Forsingle fanno uso di StringBuilder e aggiungerlo che farà o convertire questo in forma di dizionario

// 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

Grazie, questo è abbastanza buono per me domanda – Jeff

19

Tutti gli raggruppate oggetti, o tutti i tipi ? Sembra che si può fare,:

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: Se desidera in un dizionario, si può semplicemente utilizzare:

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

Non c'è bisogno di selezionare in coppie e poi costruisci il dizionario

+0

Siamo spiacenti per la domanda non chiara. La tua soluzione è molto simile a quella di cui ho bisogno, ma voglio avere tutti i risultati di raggruppamento in un singolo oggetto, non in un oggetto per tipo – Jeff

+1

@Jeff: la risposta che hai accettato è effettivamente uguale alla mia ... solo in un dizionario . I risultati * sono * tutti in un singolo oggetto ('query'). Non è ancora chiaro cosa vuoi ottenere che la mia soluzione non faccia per te. Se stai andando a raggruppare per tipo, hai * ottenuto * di avere un oggetto per gruppo, ma qui 'query' è la query che * ti darà * tutti quei gruppi. –

+0

Beh, so che tipi cercherò in una lista raggruppata, quindi averlo nel dizionario sembra essere abbastanza facile da creare un oggetto al di fuori della query – Jeff

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

lato: in generale, se si fa un nuovo select {..} si inserisce qualcosa nel DB quando si aggiornaChanges? –

+0

@DanyKhalife non è necessario chiamare updateChanges quando si utilizzano le istruzioni selezionate. Se lo usi, non inserirà nulla, eseguirà solo un'istruzione select nel DB. – daryal

1

Se si desidera essere in grado di eseguire una ricerca su ciascun tipo per ottenere la sua frequenza, sarà necessario trasformare l'enumerazione in un dizionario.

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

Le risposte qui mi ha fatto vicino, ma nel 2016, sono stato in grado di scrivere il seguente LINQ:

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

questo è interessante e istruttivo! Grazie! –

0

Questo è un grande articolo per la sintassi necessaria per creare nuovi oggetti da una query LINQ .

Tuttavia, se le assegnazioni per riempire i campi dell'oggetto sono qualcosa di più di semplici assegnazioni, ad esempio, l'analisi di stringhe in numeri interi e una di esse non riesce, non è possibile eseguire il debug di questo. Non è possibile creare un breakpoint su nessuno dei singoli incarichi.

E se si spostano tutti i compiti in una subroutine e si restituisce un nuovo oggetto da lì e si tenta di impostare un punto di interruzione in tale routine, è possibile impostare un punto di interruzione in tale routine, ma il punto di interruzione non verrà mai attivato.

Così, invece di:

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

ho invece fatto questo:

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

Questo mi ha permesso facilmente il debug e capire quale incarico stava venendo a mancare.In questo caso, a XElement mancava un campo che stavo analizzando per impostare nel SuggestionItem.

Mi sono imbattuto in questi trucchi con Visual Studio 2017 durante la scrittura di unit test per una nuova routine di libreria.