2016-06-01 17 views
8

ho un oggetto simile come mostrato di seguitoC aggregando # attributi in una lista

public class SampleObject 
{ 
    public int MsfId { get; set; } 
    public List<string> PgId { get; set; } 
    public List<string> DcId { get; set; } 
} 

nell'aggregazione sopra dei valori PgId raggruppati per MsfId. Lo stesso vale per lo DcId.

Ad esempio:

MsfId: 100 
PgId: "abc" 
DcId: "123" 

MsfId: 100 
PgId: "def" 
DcId: "456" 

MsfId: 100 
PgId: "ghi" 
DcId: "789" 

MsfId: 101 
PgId: "abc" 
DcId: "123" 

Come scrivere una query LINQ per aggregare questo e creare un elenco di SampleObjects come qui di seguito?

MsfId: 100 
PgId: "abc", "def", "ghi" 
DcId: "123", "456", "789" 

MsfId: 101 
PgId: "abc" 
DcId: "123" 
+0

Quale sarebbe esattamente il criterio di raggruppamento? L'uguaglianza di 'MsfId'? – Codor

+0

PgId: "abc" o PgCodes: "abc"? –

+4

Sembra un'operazione standard di 'GroupBy', qual è il problema? –

risposta

7

aggregazione Prova in questo modo:

var result = col.GroupBy(x => x.MsfId) 
       .Select(x => new SampleObject { 
         MsfId = x.Key, 
         PgCodes = x.Select(t=>t.PgId).ToList(), 
         DcCodes = x.Select(t=>t.DcId).ToList() 
       }); 
+0

Potrebbe essere necessario un '.Distinct()' quando si seleziona 'PgCodes' - altrimenti sto scommettendo che l'OP ottiene duplicati. – Jamiec

+0

Penso che 'Seleziona' ottieni la raccolta, Che ne dici' seleziona molti' – Eldho

+0

Estensione della domanda e se ci sono altri attributi con MsfId che sarebbero anche unici, come posso impostarli quando si crea un nuovo SampleObject {} – SteelBird82

4

Scenario 1

public class SampleObject 
{ 
    public int MsfId { get; set; } 
    public List<string> PgId { get; set; } 
    public List<string> DcId { get; set; } 
} 

Scenario 2

public class SampleObjectSource 
{ 
    public int MsfId { get; set; } 
    public string PgId { get; set; } 
    public string DcId { get; set; } 
} 

Scenario 1 Risposta

var collection = new List<SampleObject>(); 
    var result = collection.GroupBy(y => y.MsfId) 
        .Select(y => new SampleObject 
        { 
         MsfId = y.Key, 
         PgId = y.SelectMany(g => g.PgId).Distinct().ToList(), 
        }).ToList(); 

Scenario 2

var collection2 = new List<SampleObjectSource>(); 
var result1 = collection2.GroupBy(y => y.MsfId) 
       .Select(y => new SampleObject 
       { 
        MsfId = y.Key, 
        PgId = y.Select(h => h.PgId).Distinct().ToList(), 
       }).ToList(); 

Aggiornamento: Si prega di vedere il dotnetfiddle

+1

Questo fa non funziona perché 'SelectMany (p => p.PgId)' restituisce un 'IEnumerable '. Metti alla prova la tua soluzione prima di postare per favore. –

+0

@Abbondanza qui 'PgId' è pubblico Elenco PgId {get; impostato; } se non selezioni, otterrai la raccolta di lista – Eldho

3

È necessario raggruppare gli elementi con una query. Questo raggruppamento LINQ creerà una collezione di collezioni (con una chiave)

Ho appena fatto un esempio funzionante completo:

// The class to start with 
public class SampleObjectSource 
{ 
    public int MsfId { get; set; } 
    public string PgId { get; set; } 
    public string DcId { get; set; } 
} 

// the result class 
public class SampleObject 
{ 
    public int MsfId { get; set; } 
    public List<string> PgId { get; set; } 
    public List<string> DcId { get; set; } 
} 

// for example: 
public class Example 
{ 
    public Example() 
    { 
     // create a list that contains the items. 
     var list = new List<SampleObjectSource> 
     { 
      new SampleObjectSource { MsfId= 100, PgId= "abc", DcId= "123" }, 
      new SampleObjectSource { MsfId= 100, PgId= "def", DcId= "456" }, 
      new SampleObjectSource { MsfId= 100, PgId= "ghi", DcId= "789" }, 
      new SampleObjectSource { MsfId= 101, PgId= "abc", DcId= "123" }, 
     }; 

     // the linq query that does the grouping. 
     var query = from item in list 
        // group the items by MsfId 
        group item by item.MsfId into itemgroup 
        // create the new class and initialize the properties 
        select new SampleObject 
        { 
         // the grouping item is the .Key (in this case MsfId) 
         MsfId = itemgroup.Key, 
         // the itemgroup is a collection of all grouped items, so you need to select the properties you're interrested in. 
         DcId = itemgroup.Select(i => i.DcId).ToList(), 
         PgId = itemgroup.Select(i => i.PgId).ToList() 
        }; 

     // show the results in the Output window. 
     foreach (var item in query) 
     { 
      Trace.WriteLine($"MsfId: {item.MsfId}"); 
      // some trick to format a list of strings to one string 
      Trace.WriteLine($"PgId: {string.Join(", ", item.PgId.Select(s => Quote(s)))}"); 
      Trace.WriteLine($"DcId: {string.Join(", ", item.DcId.Select(s => Quote(s)))}"); 
      Trace.WriteLine(""); 
     } 
    } 

    // this method will surround the passed string with quotes. 
    private string Quote(string item) 
    { 
     return "\"" + item + "\""; 
    } 
} 

risultati:

MsfId: 100 
PgId: "abc", "def", "ghi" 
DcId: "123", "456", "789" 

MsfId: 101 
PgId: "abc" 
DcId: "123" 
2

fare tutto con uno GroupBy utilizzando l'overload appropriato. Working Fiddle Here.

Nota l'uso di SelectMany per concatenare le raccolte raggruppate in una sola.

var result = sampleObjects 
    .GroupBy(
     o => o.MsfId, 
     (k, g) => new SampleObject 
      { 
       MsfId = k, 
       PgId = g.SelectMany(p => p.PgId).ToList(), 
       DcId = g.SelectMany(p => p.DcId).ToList() 
      }); 

Se si desidera rimuovere i duplicati dalle collezioni considerano Distinct() esempio

var result = sampleObjects 
    .GroupBy(
     o => o.MsfId, 
     (k, g) => new SampleObject 
      { 
       MsfId = k, 
       PgId = g.SelectMany(p => p.PgId).Distinct().ToList(), 
       DcId = g.SelectMany(p => p.DcId).Distinct().ToList() 
      }); 
+1

Appena testato la soluzione, il 'SelectMany' non funziona in questo caso. All'interno dell'istruzione GroupBy, la 'g' non è una lista di liste, quindi non puoi appiattire nulla. Basta cambiarlo in 'Select()' per una soluzione funzionante. _ (e un +1) _ –

+0

@JeroenvanLangen non dipende dal tipo di 'sampleObjects', presumibilmente si sta usando un' IEnumerable 'come' source'? – Jodrell

+2

Questo non funziona perché 'SelectMany (p => p.PgId)' restituisce un 'IEnumerable '. Metti alla prova la tua soluzione prima di postare per favore. –